关于 threejs-materials-lighting
面向 three.js 场景开发与排错的技能,涵盖材质、灯光、阴影和基于图像的照明;示例针对并验证于 r186。
主要功能
- 01选择 PBR、非受光和调试材质
- 02组合补光与主光
- 03启用并调整阴影
- 04添加环境贴图反射
- 05设置 PBR 纹理色彩空间
适用场景
- 01排查网格呈黑色或扁平的问题
- 02为场景设置阴影
- 03添加 HDR 环境反射
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill threejs-materials-lighting安装后在 Claude Code 中输入/threejs-materials-lighting确认已加载。
附带文件references/materials-lights-table.md
详细介绍
three.js 材质与光照
让 three.js 表面呈现理想效果:选择合适的材质,为场景布光, 启用阴影,并添加基于图像的光照。模式适用于 r186,并已针对 r186 验证(自 r155 起,默认采用基于物理的光照)。
适用场景
- 网格渲染为黑色或显得平淡、需要选择材质、添加光源、启用阴影,或设置环境贴图反射(IBL)时使用。
- 代码创建
MeshStandardMaterial、DirectionalLight等,或设置renderer.shadowMap.enabled或scene.environment时使用。
**不适用场景:**渲染器/相机/循环 → threejs-scene-setup。
加载模型(本主题可为其 PBR 材质提供补充)→ threejs-gltf-loading。
自定义 GLSL/ShaderMaterial 属于独立主题;有关通用概念,请参阅
shader-programming。
核心工作流
- 根据需求选择材质。 逼真效果使用
MeshStandardMaterial(PBR:roughness、metalness,会响应光照/IBL);清漆/透射效果使用MeshPhysicalMaterial; UI/扁平效果使用MeshBasicMaterial(无光照,不受光源影响); 调试使用MeshNormalMaterial/MeshDepthMaterial。 - 添加光源,否则什么也看不到。 受光照材质需要光源和/或
scene.environment。组合柔和的补光(AmbientLight/HemisphereLight)与 主光DirectionalLight。 - 注意光照强度。 自 r155 起,光照基于物理;现代强度数值高于旧教程(主光
DirectionalLight≈ 1–3)。 - 在三个位置启用阴影。 设置
renderer.shadowMap.enabled = true、光源的castShadow = true,以及每个网格的castShadow/receiveShadow。然后 调整光源的阴影相机,使其适配场景。 - 使用环境贴图获得自然的反射。 将等距柱状投影纹理或经过 PMREM 处理的纹理赋给
scene.environment;PBR 材质会自动使用它。 - 在真实光照下验证 — 确认表面会响应主光(高光会移动)、阴影落在预期位置, 且反射看起来合理。
模式
1. 使用三光源布光的 PBR 材质
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. 无光照材质(无需光源)
// 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. 阴影(必需的三个开关 + 相机调整)
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap; // soft by default since r182
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 纹理
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. 来自 HDR 环境的基于图像的光照
import { HDRLoader } from 'three/addons/loaders/HDRLoader.js'; // RGBELoader before r180
new HDRLoader().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;
常见问题
- 网格全黑 → 使用了受光照材质,但没有光源,也没有
scene.environment。 添加光源或环境贴图;如需确认几何体正常,可暂时替换为MeshBasicMaterial/MeshNormalMaterial。 - 即使有光源,场景仍然太暗 → 使用了旧教程中的强度数值。r155+ 采用基于物理的光照; 提高强度(主光 ≈ 2–3)或添加环境贴图。
- 阴影没有出现 → 漏掉了三个开关之一
(
renderer.shadowMap.enabled、light.castShadow、网格的castShadow/receiveShadow)。 - 阴影被截断或呈块状 →
DirectionalLight的正交shadow.camera视锥过大/过小,或未覆盖整个场景;收紧left/right/top/bottom/near/far并提高shadow.mapSize。使用new THREE.CameraHelper(light.shadow.camera)将其可视化。 - 阴影痤疮 / 阴影悬浮 → 调整
light.shadow.bias(较小的负值)和light.shadow.normalBias。 - 颜色看起来褪色/过亮 → 颜色(反照率)纹理需要设置
texture.colorSpace = THREE.SRGBColorSpace;法线/粗糙度/金属度贴图必须 保持线性(保留为NoColorSpace)。 - PointLight 阴影严重拖慢性能 → 点光源会将场景渲染 6 次
(立方体贴图)。优先使用一个投射阴影的
DirectionalLight;其他位置使用开销更低的替代方案。
参考资料
- 有关材质速查表(不同外观对应哪种
Mesh*Material)、光源类型及其参数/单位、 透明度与alphaTest的顺序,以及无需 HDR 文件时通过PMREMGenerator/RoomEnvironment实现 IBL 的方法,请阅读references/materials-lights-table.md。
相关技能
threejs-scene-setup— 渲染器、相机和循环(设置shadowMap、色调映射)。threejs-gltf-loading— 模型加载时带有 PBR 材质,可使用此技能进行调整。shader-programming— 自定义着色器效果(与引擎无关的概念)。
评论
支持 Markdown