本文档涵盖了Three.js中灯光与阴影的关键概念和实现方法,基于实际代码示例进行讲解。
1. 灯光与阴影基础设置
1.1 渲染器阴影设置
要在Three.js中启用阴影,必须对渲染器进行相应配置:
// 创建渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true, // 开启抗锯齿
});
// 设置渲染器允许投射阴影
renderer.shadowMap.enabled = true;
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.outputColorSpace = THREE.SRGBColorSpace;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
// 设置阴影类型
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
1.2 物体阴影设置
要使物体能够投射和接收阴影,需要分别设置相应的属性:
// 设置物体可以投射阴影
sphere.castShadow = true;
// 设置物体可以接收阴影
sphere.receiveShadow = true;
// 平面接收阴影
planeMesh.receiveShadow = true;
planeMesh.castShadow = true;
2. 环境光 (AmbientLight)
环境光会均匀照亮场景中的所有物体,不会产生阴影。
// 添加环境光
let ambientLight = new THREE.AmbientLight(0xffffff, 0.1);
scene.add(ambientLight);
3. 平行光 (DirectionalLight)
平行光模拟太阳光,光线方向一致,常用于主光源。
// 添加平行光
let directionalLight = new THREE.DirectionalLight(0xffffff, 0.6);
directionalLight.position.set(10, 10, 0);
// 默认平行光的目标是原点
directionalLight.target.position.set(0, 0, 0);
scene.add(directionalLight);
// 设置光投射阴影
directionalLight.castShadow = true;
// 添加平行光辅助器
let directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight);
scene.add(directionalLightHelper);
// 配置阴影参数
directionalLight.shadow.camera.left = -10;
directionalLight.shadow.camera.right = 10;
directionalLight.shadow.camera.top = 10;
directionalLight.shadow.camera.bottom = -10;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 50;
// 设置阴影的纹理大小
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
4. 聚光灯 (SpotLight)
聚光灯从一个点向特定方向发射光线,形成锥形照明区域。
// 添加聚光灯
let spotLight = new THREE.SpotLight(0xffffff, 2);
spotLight.position.set(0, 10, 0);
spotLight.target.position.set(0, 0, 0);
spotLight.castShadow = true;
// 聚光灯特有参数
spotLight.angle = Math.PI / 8; // 光线锥的角度
spotLight.distance = 100; // 光线最远照射距离
spotLight.penumbra = 0.5; // 半影衰减参数 (0-1)
spotLight.decay = 2; // 衰减率 (仅在 physically correct lighting 时有效)
scene.add(spotLight);
// 添加聚光灯辅助器
let spotLightHelper = new THREE.SpotLightHelper(spotLight);
scene.add(spotLightHelper);
// 配置阴影参数
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
5. 点光源 (PointLight)
点光源从一个点向四周发射光线,类似灯泡的效果。
// 添加点光源
let pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(0, 5, 0);
pointLight.castShadow = true;
scene.add(pointLight);
// 点光源特有参数
pointLight.distance = 15; // 光线最远照射距离
pointLight.decay = 2; // 衰减率
// 配置阴影参数
pointLight.shadow.mapSize.width = 2048;
pointLight.shadow.mapSize.height = 2048;
// 添加点光源辅助器
let pointLightHelper = new THREE.PointLightHelper(pointLight);
scene.add(pointLightHelper);
6. 透明度纹理与阴影设置
对于具有透明度的物体,需要特殊处理才能正确显示阴影。
let alphaTexture = new THREE.TextureLoader().load("./texture/16.jpg");
const material3 = new THREE.MeshPhysicalMaterial({
color: 0xffcccc,
alphaMap: alphaTexture, // 透明度贴图
transparent: true, // 启用透明度
side: THREE.DoubleSide, // 双面渲染
alphaTest: 0.5, // 透明度阈值
shadowSide: THREE.BackSide // 阴影渲染面
});
const box = new THREE.Mesh(boxGeometry, material3);
box.position.set(-4, 0, 0);
scene.add(box);
// 设置透明物体的阴影属性
box.receiveShadow = true;
box.castShadow = true;
// 解决常见阴影问题
pointLight.shadow.bias = -0.01; // 阴影偏移,减少阴影瑕疵
7. 级联阴影映射 (CSM - Cascaded Shadow Maps)
对于大场景,使用级联阴影映射可以提高阴影质量。
import { CSM } from "three/addons/csm/CSM.js";
// 参数配置
const params = {
orthographic: false,
fade: true,
far: 1000,
mode: "practical",
lightX: -1,
lightY: -1,
lightZ: -1,
margin: 100,
lightFar: 1000,
lightNear: 1
};
// 创建CSM实例
let csm = new CSM({
maxFar: params.far,
cascades: 4, // 级联数量
parent: scene,
shadowMapSize: 1024, // 阴影贴图大小
lightDirection: new THREE.Vector3(
params.lightX,
params.lightY,
params.lightZ
).normalize(),
camera: camera,
});
csm.fade = true; // 启用淡入淡出效果
csm.updateFrustums(); // 更新视锥体
// 动画循环中更新CSM
function animate() {
controls.update();
camera.updateMatrixWorld();
csm.update(); // 更新CSM
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
// 为材质设置CSM支持
csm.setupMaterial(material1);
csm.setupMaterial(material2);
csm.setupMaterial(material3);
8. 灯光辅助工具
Three.js提供了多种灯光辅助器,帮助调试和可视化灯光效果。
// 平行光辅助器
let directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight);
scene.add(directionalLightHelper);
// 聚光灯辅助器
let spotLightHelper = new THREE.SpotLightHelper(spotLight);
scene.add(spotLightHelper);
// 点光源辅助器
let pointLightHelper = new THREE.PointLightHelper(pointLight);
scene.add(pointLightHelper);
// 阴影相机辅助器
let cameraHelper = new THREE.CameraHelper(directionalLight.shadow.camera);
scene.add(cameraHelper);
9. HDR环境贴图
使用HDR贴图可以提供高质量的环境光照。
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
// 加载HDR环境贴图
let rgbeLoader = new RGBELoader();
rgbeLoader.load("./texture/Video_Copilot-Back Light_0007_4k.hdr", (envMap) => {
// 设置球形贴图
envMap.mapping = THREE.EquirectangularReflectionMapping;
// 设置环境贴图
scene.background = envMap;
// 或者设置为场景环境
// scene.environment = envMap;
});
10. 材质配置
使用合适的材质以获得最佳的灯光和阴影效果。
// 使用MeshPhysicalMaterial获得更好的物理渲染效果
const material1 = new THREE.MeshPhysicalMaterial({
color: 0xccccff,
});
const material2 = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
});
const material3 = new THREE.MeshPhysicalMaterial({
color: 0xffcccc,
});
总结
本章详细介绍了Three.js中灯光与阴影的各个方面,包括:
- 启用阴影的基础设置
- 不同类型的灯光(环境光、平行光、聚光灯、点光源)
- 透明物体的阴影处理
- 级联阴影映射(CSM)技术
- 灯光辅助工具的使用
- HDR环境贴图的应用
通过合理配置这些灯光和阴影参数,可以创建出逼真的3D场景效果。注意阴影贴图大小、偏移量、衰减等参数的调整,可以有效改善阴影质量,避免常见的阴影瑕疵。