"世界并不黑暗,只是你没打光。" ------ 一个没有灯光的 Three.js 场景
一、引子:没有光,何来三维世界?
在现实世界中,如果没有光,你什么也看不到。在虚拟的 3D 世界里,这道理同样成立。
在 Three.js 里,光照系统就像舞台剧的灯光导演: 你要为演员(模型)打光、为情绪渲染氛围、为观众(用户)展现细节。
今天我们将穿越照明的五重境界,从平光到物理真实,从基础到炫技,用代码和底层原理照亮你三维世界的每一寸角落。
二、照明五宗"光":谁才是舞台上的主角?
让我们先熟悉一下 Three.js 中的光照种类(就像认识一支光影剧团):
1️⃣ AmbientLight
- 环境光
"我负责让世界不至于一片漆黑。"
- 整个场景平均照亮,无方向、无阴影
- 没有立体感,但是友好的基础照明
js
const ambient = new THREE.AmbientLight(0xffffff, 0.3)
scene.add(ambient)
2️⃣ DirectionalLight
- 平行光(太阳来了)
"我来自天外,但照得你头皮发烫。"
- 类似太阳光,照射方向固定,光线平行
- 支持阴影,适合大范围、清晰的影子效果
js
const sun = new THREE.DirectionalLight(0xffffff, 1)
sun.position.set(10, 10, 10)
sun.castShadow = true
scene.add(sun)
🌞 实战技巧 :使用 light.target
指定照射目标(比如一只逃跑的老鼠)。
3️⃣ PointLight
- 点光源(灯泡的亲戚)
"我是一颗孤独的光点,温暖着周围。"
- 从一个点向四周发射光线,类似灯泡或法球
- 有距离衰减,越远越暗
- 可投射阴影,但要小心性能
js
const bulb = new THREE.PointLight(0xffaa00, 1, 100)
bulb.position.set(0, 10, 0)
scene.add(bulb)
💡 小技巧 :使用 light.decay
控制真实感衰减(需配合 physicallyCorrectLights = true
)。
4️⃣ SpotLight
- 聚光灯(舞台最强气氛组)
"只照我想照的人。"
- 有方向、有锥角、有阴影
- 可用于手电筒、聚光舞台等效果
js
const spotlight = new THREE.SpotLight(0xffffff, 1)
spotlight.position.set(5, 10, 5)
spotlight.angle = Math.PI / 6 // 控制锥角大小
spotlight.castShadow = true
scene.add(spotlight)
🎯 推荐搭配 :使用 spotLightHelper
查看照明区域。
5️⃣ RectAreaLight
- 面光源(广告灯箱专用)
"我不是点,而是一整片柔和的光。"
- 真实、柔和,适合室内灯带、面板灯
- 只能影响
MeshStandardMaterial
和MeshPhysicalMaterial
- 不支持阴影
js
const rectLight = new THREE.RectAreaLight(0xffffff, 5, 4, 2)
rectLight.position.set(0, 5, 0)
rectLight.lookAt(0, 0, 0)
scene.add(rectLight)
📦 记得引入 :RectAreaLightUniformsLib.init()
初始化支持。
三、光照原理小课堂(不讲公式,只讲感情)
光照计算三大成分:
- 环境光(Ambient):统一底色,就像天很亮的时候,看哪里都亮。
- 漫反射(Diffuse):表面朝向光源的部分亮,背光部分暗,给模型立体感。
- 镜面反射(Specular):表面越光滑,越容易出现高光(比如光照打在油脸上...)。
这些原理被集成在材质中:
js
const material = new THREE.MeshStandardMaterial({
color: 0x6699ff,
roughness: 0.5, // 越小越光滑
metalness: 0.3 // 金属感
})
🎨 你选择的材质决定了光照是否"入戏"! MeshBasicMaterial
:不吃光 MeshStandardMaterial
:吃光还懂物理
四、阴影的真相:不是谁都能投影
要开启阴影系统,有三件事必须到位:
js
renderer.shadowMap.enabled = true
light.castShadow = true
mesh.castShadow = true
floor.receiveShadow = true
⚠️ 记住:
- 光源必须支持阴影(例如
DirectionalLight
) - 对象必须**"投影"和"接收"**
- 材质不能是基础材质(
MeshBasicMaterial
不会管光)
五、高级技巧锦囊 🌟
1. 使用 physicallyCorrectLights
更真实
js
renderer.physicallyCorrectLights = true
这会启用真实世界的光照衰减,让 intensity
变得更有物理意义。你会发现:
- 聚光灯不再无敌
distance
和decay
开始发挥作用
2. 动态灯光:为场景注入灵魂
js
function animate() {
requestAnimationFrame(animate)
pointLight.position.x = Math.sin(Date.now() * 0.001) * 5
renderer.render(scene, camera)
}
一个会跳舞的光源 = 一个有灵魂的场景 ✨
3. 视觉调试助手:让光照不再神秘
js
scene.add(new THREE.DirectionalLightHelper(directionalLight, 5))
scene.add(new THREE.CameraHelper(directionalLight.shadow.camera))
六、结语:掌控光,就掌控了舞台
Three.js 的光照系统并非简单的开关,它是一套模拟真实世界光影互动的复杂系统。
而你,作为光的主宰者,要做到:
- 知道用什么灯打什么光
- 用材质配合光线表达情绪
- 在性能和视觉之间取得平衡
"你无法创造真实的世界,但你可以让虚拟世界更接近真实。"
✨ 延伸阅读与练习:
- 🔬 使用
MeshPhysicalMaterial
实现玻璃与反射 - 🌄 配合环境贴图与光探针实现全局光照
- 🔧 自定义光照 Shader:打造属于你的特效光(Volumetric God Rays)