Backface culling

백페이스 컬링

Skipping faces that point away from the camera entirely, so the GPU never wastes work rasterizing something no one can see.

Also known as: Face cullingmaterial.side
···
html
<div class="sub-caps"><span>single-sided · culled</span><span>double-sided</span></div>
css
.sub-caps{position:absolute;left:0;right:0;bottom:6%;display:flex;justify-content:space-around;font-size:clamp(8px,2.4vmin,12px);color:#dfe3ffcc;text-align:center;padding:0 3%}
js
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x0b0b14);
const camera = new THREE.PerspectiveCamera(42, 1, 0.1, 100);
camera.position.set(0, 0.3, 6);

const geo = new THREE.PlaneGeometry(2.1, 2.6);
const single = new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color: 0xff9a5a, side: THREE.FrontSide, roughness: 0.5 }));
single.position.x = -1.7;
const double = new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color: 0x8ecbff, side: THREE.DoubleSide, roughness: 0.5 }));
double.position.x = 1.7;
scene.add(single, double);
const key = new THREE.DirectionalLight(0xffffff, 1.7); key.position.set(3, 4, 5); scene.add(key);
scene.add(new THREE.AmbientLight(0xffffff, 0.55));

function resize() { renderer.setSize(innerWidth, innerHeight); camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); }
addEventListener('resize', resize); resize();
renderer.setAnimationLoop((t) => {
  const r = t * 0.0005;
  single.rotation.y = r; double.rotation.y = r;
  renderer.render(scene, camera);
});

A closed shape — a cube, a character that reads as solid — always has its inner faces hidden behind its outer ones from the camera’s point of view. Drawing those inner faces every time anyway means the GPU wastes half its effort rasterizing pixels no one will ever see. Backface culling checks whether each face’s direction (its normal) points toward or away from the camera ahead of time, and simply skips drawing it if it’s facing away.

It’s a performance win and a trap at the same time — leave the default (single-sided) setting on a thin plane or cloth that needs to be visible from both sides, and it vanishes entirely the moment you look at it from behind. three.js’s material.side lets you pick between FrontSide (default, culled), BackSide, and DoubleSide (draws both faces, no culling).

Blender, Maya, and C4D viewports all have a “backface culling” toggle too, so you can preview exactly which faces a real-time renderer would actually throw away. Deleting faces that will genuinely never be seen — the inside of a wall, the underside of terrain — at the modeling stage is the same optimization, done by hand instead of automatically.

When to use

Keep the default (culling on) to save real-time performance; switch to DoubleSide for cloth or thin panels that must be visible from both sides.