mcpField
T
threejs-materials-lighting

threejs-materials-lighting

github.com/gamedev-skills创意与媒体5.4k6.2k 次安装今天更新
代码仓库

关于 threejs-materials-lighting

面向 three.js 场景开发与排错的技能,涵盖材质、灯光、阴影和基于图像的照明;示例针对并验证于 r186。

主要功能

  1. 01选择 PBR、非受光和调试材质
  2. 02组合补光与主光
  3. 03启用并调整阴影
  4. 04添加环境贴图反射
  5. 05设置 PBR 纹理色彩空间

适用场景

  1. 01排查网格呈黑色或扁平的问题
  2. 02为场景设置阴影
  3. 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。

核心工作流

  1. 根据需求选择材质。 逼真效果使用 MeshStandardMaterial(PBR:roughness、 metalness,会响应光照/IBL);清漆/透射效果使用 MeshPhysicalMaterial; UI/扁平效果使用 MeshBasicMaterial(无光照,不受光源影响); 调试使用 MeshNormalMaterial/MeshDepthMaterial。
  2. 添加光源,否则什么也看不到。 受光照材质需要光源和/或 scene.environment。组合柔和的补光(AmbientLight/HemisphereLight)与 主光 DirectionalLight。
  3. 注意光照强度。 自 r155 起,光照基于物理;现代强度数值高于旧教程(主光 DirectionalLight ≈ 1–3)。
  4. 在三个位置启用阴影。 设置 renderer.shadowMap.enabled = true、光源的 castShadow = true,以及每个网格的 castShadow/receiveShadow。然后 调整光源的阴影相机,使其适配场景。
  5. 使用环境贴图获得自然的反射。 将等距柱状投影纹理或经过 PMREM 处理的纹理赋给 scene.environment;PBR 材质会自动使用它。
  6. 在真实光照下验证 — 确认表面会响应主光(高光会移动)、阴影落在预期位置, 且反射看起来合理。

模式

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