Navigate

Search topics across all sections

GitHub
Materials

Basic Materials

Think of materials as the "skin" of your 3D objects. Basic materials are the simplest ones Three.js offers — they are fast, predictable, and some of them do not need lights at all to show up on screen.

You add a beautiful mesh to your scene with MeshStandardMaterial, but it shows up completely black. You try changing the color — still black. You spend 20 minutes debugging before realizing there are no lights in your scene. If you had used MeshBasicMaterial, the color would have shown up immediately.

terminal
Mesh renders but appears completely black despite having a color set.

Real-world

Imagine you are standing in a paint store with four types of paint in front of you.

Basic is like spray paint — flat, solid color, no light interaction at all. What you spray is what you see.

Normal is like a mood ring — it changes color based on the angle you look at it, showing you which direction each part of the surface faces.

Lambert is like chalk paint — matte and soft, it reacts to light but never looks shiny.

Phong is like nail polish — it has that glossy, reflective highlight that shifts as you move around it.

Which Material Should I Pick?

Here is a quick decision flow. Start at the left and follow the arrows.

Need lights?

Does your object need to react to scene lighting?

No lights needed

Basic or Normal

Matte surface?

Lambert (cheap, soft)

Shiny surface?

Phong (specular highlight)

Guided Walkthrough

Let us build up from the simplest material to a shiny one, step by step.

Step 1 — A flat-colored sphere (no lights needed)

step-1-basic.tsxTSX
<mesh>
  <sphereGeometry args={[1, 32, 32]} />
  <meshBasicMaterial color="#4488ff" />
</mesh>

This creates a blue sphere that shows up instantly. No lights, no setup — just color. Think of it like spray painting a ball.

Step 2 — A matte surface that reacts to light

step-2-lambert.tsxTSX
<ambientLight intensity={0.3} />
<directionalLight position={[5, 5, 5]} />
<mesh>
  <sphereGeometry args={[1, 32, 32]} />
  <meshLambertMaterial color="#44ccaa" />
</mesh>

Now we added lights and switched to Lambert. The sphere looks soft and matte, like a chalk-painted ball. The side facing the light is brighter, giving it a 3D feel.

Step 3 — Adding a shiny highlight

step-3-phong.tsxTSX
<mesh>
  <sphereGeometry args={[1, 32, 32]} />
  <meshPhongMaterial
    color="#88ff44"
    specular="#ffffff"
    shininess={200}
  />
</mesh>

Phong adds a bright spot where the light hits — like a glossy nail polish reflection. The shininess value controls how tight that highlight is. Higher numbers mean a smaller, sharper spot.

Basic (No Light Needed)Standard (Needs Light)
MaterialComparison.tsx
<mesh>
  <sphereGeometry args={[1, 32, 32]} />
  <meshBasicMaterial color="#4488ff" />
</mesh>
{/* No lights needed — always visible */}

MeshBasicMaterial shows flat color with no shading — always visible, even without lights.

What you just learned

MeshBasicMaterial ignores all lights — what you set is what you see

MeshNormalMaterial maps surface angles to colors, perfect for debugging geometry

MeshLambertMaterial gives you a cheap matte look but needs lights in the scene

MeshPhongMaterial adds a specular highlight for shiny, glossy surfaces

Question

If MeshBasicMaterial does not respond to lights, why would you ever use it in a serious project? Hint: think about UI elements floating in 3D space, always-visible markers, or a skybox that should not get darker when the sun sets.

Think about it...

You have a scene with no lights at all. Which materials will still show their color on screen?

Try These Challenges

Put what you learned into practice. Try each challenge in the demo above using the Leva controls, then check the solution.

Try This!

Beginner

Set lightIntensity to 0 — which spheres are still visible?

Try This!

Beginner

Toggle wireframe on all materials

Try This!

Intermediate

Move the light behind the objects

These are the patterns that trip up developers most often. Switch between Wrong and Fixed to compare the code side by side.

1
Using MeshStandardMaterial just to see a shape
The mesh appears black because there are no lights
Don't do this
debug-material.tsxTSX
// You just want to see a red cube for debugging
<mesh>
  <boxGeometry />
  <meshStandardMaterial color="red" />
</mesh>
// No lights in scene = completely black cube
MeshStandardMaterial needs lights to be visible. When you just want to see a shape on screen, MeshBasicMaterial is the right choice because it shows the exact color you set, regardless of whether lights exist in the scene.
2
Forgetting needsUpdate when swapping textures
Material stays blank after changing its texture at runtime
Don't do this
needs-update.tsxTSX
// Swap texture at runtime
material.map = newTexture;
// Nothing changes — the shader is still compiled
// for the old configuration
When you add or remove a texture from a material, the underlying shader needs to be recompiled. Setting material.needsUpdate = true triggers that recompilation. You only need this when the structure changes (adding/removing maps), not for simple color changes.

Best Practices

Use Basic for debug visuals

When you just need to see a shape, wireframe, or bounding box, reach for MeshBasicMaterial. It works without lights and is the cheapest material to render.

Prefer Lambert over Phong for matte

If a surface has no visible shiny spot, Lambert is faster than Phong. It skips the specular calculation entirely, saving GPU work on every pixel.

Normal material for geometry checks

Swap in MeshNormalMaterial to instantly check if your geometry normals look correct. Unexpected colors mean the normals are flipped or missing.

Dispose materials you no longer need

Call material.dispose() when a material is no longer used. This frees the GPU shader program and prevents memory leaks in long-running apps.