阴影主要由 castShadow
和 receiveShadow
控制,并通过不同类型的光源 (DirectionalLight
、SpotLight
、PointLight
) 生成。我们将系统地整理与阴影相关的知识点。
1️⃣ 基础概念
castShadow
🎭:物体是否投射阴影。receiveShadow
🏞️:物体是否接收阴影。renderer.shadowMap.enabled = true
✅:全局开启阴影渲染。renderer.shadowMap.type
📦:设置阴影质量,常见类型:
-
THREE.BasicShadowMap
(性能高但质量低)THREE.PCFShadowMap
(平滑阴影,默认值)THREE.PCFSoftShadowMap
(更柔和的阴影)THREE.VSMShadowMap
(高级阴影,适用于柔和阴影)
2️⃣ 各类光源的阴影设置
在 Three.js 中,不是所有的光源都能投射阴影:
光源类型 |
支持阴影 |
代码示例 |
|
✅ 支持 |
|
|
✅ 支持 |
|
|
✅ 支持 |
|
|
❌ 不支持 |
无 |
|
❌ 不支持 |
无 |
|
❌ 不支持 |
无 |
3️⃣ 代码分析:Directional Light 阴影
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(2, 2, -1);
scene.add(directionalLight);
directionalLight.castShadow = true; // ✅ 允许投射阴影
// 调整阴影贴图大小,影响阴影清晰度
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
// 调整阴影相机视锥体,决定阴影投射区域
directionalLight.shadow.camera.top = 2;
directionalLight.shadow.camera.bottom = -2;
directionalLight.shadow.camera.right = 2;
directionalLight.shadow.camera.left = -2;
// 调整相机的远近平面,影响阴影范围
directionalLight.shadow.camera.near = 1;
directionalLight.shadow.camera.far = 6;
// 创建 CameraHelper 可视化阴影相机
const directionalLightHelper = new THREE.CameraHelper(directionalLight.shadow.camera);
scene.add(directionalLightHelper);
📌 重点知识
shadow.mapSize
:控制阴影贴图分辨率,越大阴影越清晰,但影响性能。shadow.camera.top/bottom/left/right
:控制阴影的投影区域,过大会导致阴影模糊,过小会裁剪阴影。shadow.camera.near/far
:控制阴影投射的最近和最远范围,合理调整可优化阴影效果。
4️⃣ 代码分析:Spot Light 阴影
const spotLight = new THREE.SpotLight(0xffffff, 20, 5, Math.PI * 0.3);
spotLight.position.set(0, 2, 2);
spotLight.castShadow = true; // ✅ 允许投射阴影
// 调整阴影质量
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
// 控制阴影相机的远近平面
spotLight.shadow.camera.fov = 30;
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 6;
scene.add(spotLight);
scene.add(spotLight.target);
// 创建 CameraHelper 可视化阴影相机
const spotLightHelper = new THREE.CameraHelper(spotLight.shadow.camera);
scene.add(spotLightHelper);
📌 重点知识
shadow.camera.fov
:影响光锥大小,控制阴影范围。shadow.camera.near/far
:控制阴影渲染范围,避免不必要的计算。spotLight.target
:聚光灯照射的目标点,影响阴影方向。
5️⃣ 代码分析:Point Light 阴影
const pointLight = new THREE.PointLight(0xffffff, 3);
pointLight.position.set(-1, 1, 0);
pointLight.castShadow = true; // ✅ 允许投射阴影
// 调整阴影质量
pointLight.shadow.mapSize.width = 1024;
pointLight.shadow.mapSize.height = 1024;
// 控制阴影相机的远近平面
pointLight.shadow.camera.near = 0.1;
pointLight.shadow.camera.far = 6;
scene.add(pointLight);
// 创建 CameraHelper 可视化阴影相机
const pointLightHelper = new THREE.CameraHelper(pointLight.shadow.camera);
scene.add(pointLightHelper);
📌 重点知识
PointLight
采用cubeShadowMap
:需要渲染 6 个方向的阴影,性能开销较大。shadow.camera.near/far
:优化阴影投射范围,避免性能浪费。
6️⃣ 代码分析:阴影贴图
const textureLoader = new THREE.TextureLoader();
const bakedShadow = textureLoader.load('texture/shadow/bakedShadow.jpg');
const simpleShadow = textureLoader.load('texture/shadow/simpleShadow.jpg');
📌 重点知识
- 预渲染阴影贴图(Baked Shadow):避免实时计算阴影,提高性能。
- 透明阴影(Simple Shadow):
new THREE.MeshBasicMaterial({
color: 0x000000,
transparent: true,
alphaMap: simpleShadow
})
-
transparent: true
让黑色区域可见,白色区域透明。alphaMap
让阴影贴图应用到PlaneGeometry
。
7️⃣ 代码分析:球体阴影
sphereshadow.rotation.x = -Math.PI * 0.5;
sphereshadow.position.y = plane.position.y + 0.01;
scene.add(sphere, plane, sphereshadow);
📌 重点知识
- 手动调整阴影位置 避免阴影和地面重叠导致视觉错误。
- 动态改变阴影透明度:
sphereshadow.material.opacity = 1 - sphere.position.y * 0.3;
-
- 球体越高,阴影越淡,实现“动态阴影”效果。
8️⃣ 代码分析:阴影优化
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
📌 重点知识
PCFSoftShadowMap
:提供平滑柔和的阴影。setPixelRatio(Math.min(window.devicePixelRatio, 2))
:限制像素比,平衡清晰度和性能。
🔚 总结
知识点 |
关键参数 |
开启阴影 |
|
光源投射阴影 |
|
物体投射阴影 |
|
物体接收阴影 |
|
优化阴影 |
, |
手动优化阴影效果 |
预渲染贴图 ( ), |
🚀 通过合理调整这些参数,可以让 Three.js 的阴影更加逼真、柔和,同时兼顾性能优化!