Scene to Screen
Geometry, materials, lights
Lesson 2 of 5
What you'll learn
- Build a Mesh from a BufferGeometry primitive and a material
- Know when to reach for MeshBasicMaterial vs MeshStandardMaterial
- Understand what ambient and directional lights each contribute
A visible object in Three.js is a Mesh, and a mesh is exactly two things: a geometry (the shape — vertices, normals, UVs stored as typed arrays on a BufferGeometry) and a material (the surface — how those triangles react to color and light). Three.js ships geometry primitives so you rarely build vertex buffers by hand: BoxGeometry, SphereGeometry, PlaneGeometry, TorusKnotGeometry, and friends.
const geometry = new THREE.BoxGeometry(1, 1, 1);
const unlit = new THREE.MeshBasicMaterial({ color: 0x22d3ee });
const lit = new THREE.MeshStandardMaterial({ color: 0x22d3ee, roughness: 0.4 });
scene.add(new THREE.Mesh(geometry, lit));
// Standard materials render BLACK until you add lights:
scene.add(new THREE.AmbientLight(0xffffff, 0.2)); // uniform fill, no direction
const sun = new THREE.DirectionalLight(0xffffff, 2.5); // parallel rays, like sunlight
sun.position.set(5, 10, 7); // shines from here toward the origin
scene.add(sun);
MeshBasicMaterial is unlit: it paints its color at full strength no matter what, which makes it perfect for debugging, wireframes, and UI-ish overlays — and useless for conveying shape. MeshStandardMaterial is a physically-based (PBR) material with roughness and metalness; it computes its color from the lights, so with no lights in the scene it renders black.
Geometries and materials are both shareable: one BoxGeometry can back a thousand meshes with different materials. Geometry is the expensive part (vertex buffers on the GPU); a material is a cheap bundle of shading parameters.
Why lights matter
Shading is what makes 3D read as 3D. A directional light contributes diffuse light proportional to N·L — the dot product of a surface's normal with the light direction. Faces turned toward the light get bright; faces turned away get nothing. Ambient light then adds a small uniform floor so unlit faces aren't pure black. Modern Three.js uses physically-based lighting units and outputs sRGB by default, so intensities like 2.5 are normal.
The usual pairing is exactly the two above: one directional "sun" for shape, one dim ambient for fill. Point and spot lights come later; most scenes start here.
The black-screen checklist
Rendering black? Check in this order: is the material a lit type (Standard/Lambert/Phong) with no lights in the scene; is the mesh inside the camera frustum; did you call render after adding things. Number one is the classic.
The challenge models both materials on a real cube's six face normals: basic ignores the light entirely, standard computes ambient + N·L per face.
Run it. Each row is one cube face: basic paints every face identically, standard shades by the face's angle to the light. Move the light (try [0, 0, 7] — head-on) and watch the bars change.
You add a Mesh with MeshStandardMaterial and it renders solid black. Most likely cause?
Next: one cube is easy — the scene graph is how you build solar systems, robots, and anything with parts that move together.
Saved on this device. Sign in to sync your progress everywhere.