Skip to content
Development
Skill

/threejs-materials-lighting

Light and shade a three.js scene: choose materials (MeshStandardMaterial PBR vs unlit MeshBasicMaterial), add ambient/hemisphere/directional/point/spot lights, turn on shadow maps, and use an environment map (IBL) for realistic reflections. Use when a three.js model looks black,

From plugin
awesome-gamedev-agent-skills
45567 skills
Install
$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill threejs-materials-lighting --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/threejs-materials-lighting

Context preview

The summary Claude sees to decide when to auto-load this skill.

Light and shade a three.js scene: choose materials (MeshStandardMaterial PBR vs unlit MeshBasicMaterial), add ambient/hemisphere/directional/point/spot lights, turn on shadow maps, and use an environment map (IBL) for realistic reflections. Use when a three.js model looks black,

SKILL.md

threejs-materials-lighting.SKILL.md
name: threejs-materials-lighting
description: >
  Light and shade a three.js scene: choose materials (MeshStandardMaterial PBR vs
  unlit MeshBasicMaterial), add ambient/hemisphere/directional/point/spot lights,
  turn on shadow maps, and use an environment map (IBL) for realistic reflections.
  Use when a three.js model looks black, flat, or wrong — when the user mentions
  three.js materials, MeshStandardMaterial, lights, shadows, envMap, or PBR. For
  renderer/loop setup use threejs-scene-setup; for loading models use
  threejs-gltf-loading.

three.js Materials & Lighting

Make three.js surfaces look right: pick the correct material, light the scene, enable shadows, and add image-based lighting. Patterns target **r184**, verified against **r184** (lighting is physically based by default since r155).

When to use

  • Use when a mesh renders black or flat, when choosing a material, adding lights,

enabling shadows, or setting up environment-map reflections (IBL).

  • Use when code constructs `MeshStandardMaterial`, `DirectionalLight`, etc., or sets

`renderer.shadowMap.enabled` or `scene.environment`.

**When *not* to use:** the renderer/camera/loop → `threejs-scene-setup`. Loading models (whose PBR materials this complements) → `threejs-gltf-loading`. Custom GLSL/`ShaderMaterial` is its own topic; for the portable concept see `shader-programming`.

Core workflow

1. **Pick a material by need.** `MeshStandardMaterial` (PBR: `roughness`, `metalness`, reacts to lights/IBL) for realism; `MeshPhysicalMaterial` for clearcoat/transmission; `MeshBasicMaterial` (unlit, ignores lights) for UI/flat; `MeshNormalMaterial`/`MeshDepthMaterial` for debugging. 2. **Add light, or nothing shows.** Lit materials need a light source and/or `scene.environment`. Combine a soft fill (`AmbientLight`/`HemisphereLight`) with a key `DirectionalLight`. 3. **Mind light intensity.** Since r155, lighting is physically based; modern intensities are higher than old tutorials (a key `DirectionalLight` ≈ 1–3). 4. **Enable shadows in three places.** `renderer.shadowMap.enabled = true`, the light's `castShadow = true`, and each mesh's `castShadow`/`receiveShadow`. Then fit the light's shadow camera to the scene. 5. **Use an environment map for grounded reflections.** Assign an equirectangular or PMREM-processed texture to `scene.environment`; PBR materials pick it up automatically. 6. **Verify under real lighting** — confirm the surface responds to the key light (highlights move), shadows land where expected, and reflections look plausible.

Patterns

1. PBR material under a 3-light rig

import * as THREE from 'three';

const material = new THREE.MeshStandardMaterial({
  color: 0xcc4444,
  roughness: 0.5,     // 0 = mirror, 1 = fully matte
  metalness: 0.0,     // 0 = dielectric (plastic/wood), 1 = metal
});
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), material);
scene.add(mesh);

// Soft sky/ground fill + a directional key light.
scene.add(new THREE.HemisphereLight(0xbbddff, 0x443322, 1.0)); // sky, ground, intensity
const key = new THREE.DirectionalLight(0xffffff, 2.5);
key.position.set(5, 10, 7);
scene.add(key);

2. Unlit material (no light needed)

// MeshBasicMaterial ignores lights — for flat color, UI, or sprites/labels.
const flat = new THREE.MeshBasicMaterial({ color: 0x44aa88 });
// A textured color map should be tagged sRGB so colors aren't washed out:
const tex = new THREE.TextureLoader().load('assets/logo.png');
tex.colorSpace = THREE.SRGBColorSpace;
const logo = new THREE.MeshBasicMaterial({ map: tex, transparent: true });

3. Shadows (the three required switches + camera fit)

renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;     // softer edges

const sun = new THREE.DirectionalLight(0xffffff, 3);
sun.position.set(8, 12, 6);
sun.castShadow = true;
sun.shadow.mapSize.set(2048, 2048);                   // default 512; raise for crisp
// DirectionalLight uses an OrthographicCamera — fit it tightly to the scene:
const cam = sun.shadow.camera;
cam.near = 1; cam.far = 40;
cam.left = -15; cam.right = 15; cam.top = 15; cam.bottom = -15;
scene.add(sun);

mesh.castShadow = true;
ground.receiveShadow = true;                          // a plane to catch the shadow

4. PBR textures on a material

const loader = new THREE.TextureLoader();
const colorMap = loader.load('assets/brick_color.jpg');
colorMap.colorSpace = THREE.SRGBColorSpace;           // color maps are sRGB
const normalMap = loader.load('assets/brick_normal.jpg'); // data maps stay linear
const roughMap  = loader.load('assets/brick_rough.jpg');

const brick = new THREE.MeshStandardMaterial({
  map: colorMap,
  normalMap,
  roughnessMap: roughMap,
  metalness: 0,
});

5. Image-based lighting from an HDR environment

import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

new RGBELoader().load('assets/studio.hdr', (hdr) => {
  hdr.mapping = THREE.EquirectangularReflectionMapping;
  scene.environment = hdr;     // lights + reflects all PBR materials
  scene.background = hdr;       // optional: show it as the backdrop
});
// Optional cinematic tone curve:
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;

Pitfalls

  • **Mesh is pure black** → a lit material with no light and no `scene.environment`.

Add a light or an environment map; to confirm geometry, temporarily swap to `MeshBasicMaterial`/`MeshNormalMaterial`.

  • **Scene too dark even with lights** → old tutorial intensities. r155+ is physically

based; raise intensities (key light ≈ 2–3) or add an environment map.

  • **Shadows don't appear** → you missed one of the three switches

(`renderer.shadowMap.enabled`, `light.castShadow`, mesh `castShadow`/ `receiveShadow`).

  • **Shadows are cut off or blocky** → the `DirectionalLight`'s orthographic

`shadow.camera` frustum is too big/sm

Read more
Ships withawesome-gamedev-agent-skills

<img src="docs/assets/banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.

Get the whole plugin
Stats
458
Stars
36
Forks
Active
Maintenance
Python
Language
Apache-2.0
License
1d ago
Last commit
1mo ago
Created

Repo: gamedev-skills/awesome-gamedev-agent-skills