Three.js 阴影 (Shadow) 知识点整理

发布于:2025-03-16 ⋅ 阅读:(12) ⋅ 点赞:(0)

阴影主要由 castShadowreceiveShadow 控制,并通过不同类型的光源 (DirectionalLightSpotLightPointLight) 生成。我们将系统地整理与阴影相关的知识点。


1️⃣ 基础概念

  • castShadow 🎭:物体是否投射阴影。
  • receiveShadow 🏞️:物体是否接收阴影。
  • renderer.shadowMap.enabled = true ✅:全局开启阴影渲染。
  • renderer.shadowMap.type 📦:设置阴影质量,常见类型:
    • THREE.BasicShadowMap(性能高但质量低)
    • THREE.PCFShadowMap(平滑阴影,默认值)
    • THREE.PCFSoftShadowMap(更柔和的阴影)
    • THREE.VSMShadowMap(高级阴影,适用于柔和阴影)

2️⃣ 各类光源的阴影设置

在 Three.js 中,不是所有的光源都能投射阴影:

光源类型

支持阴影

代码示例

DirectionalLight

✅ 支持

directionalLight.castShadow = true

SpotLight

✅ 支持

spotLight.castShadow = true

PointLight

✅ 支持

pointLight.castShadow = true

AmbientLight

❌ 不支持

HemisphereLight

❌ 不支持

RectAreaLight

❌ 不支持


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)):限制像素比,平衡清晰度和性能。

🔚 总结

知识点

关键参数

开启阴影

renderer.shadowMap.enabled = true

光源投射阴影

light.castShadow = true

物体投射阴影

mesh.castShadow = true

物体接收阴影

mesh.receiveShadow = true

优化阴影

shadow.mapSize

, shadow.camera.near/far

手动优化阴影效果

预渲染贴图 (bakedShadow

), PCFSoftShadowMap

🚀 通过合理调整这些参数,可以让 Three.js 的阴影更加逼真、柔和,同时兼顾性能优化!