Three.js 光照系统进阶指南 —— 打造光明的舞台

"世界并不黑暗,只是你没打光。" ------ 一个没有灯光的 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 - 面光源(广告灯箱专用)

"我不是点,而是一整片柔和的光。"

  • 真实、柔和,适合室内灯带、面板灯
  • 只能影响 MeshStandardMaterialMeshPhysicalMaterial
  • 不支持阴影
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() 初始化支持。


三、光照原理小课堂(不讲公式,只讲感情)

光照计算三大成分:

  1. 环境光(Ambient):统一底色,就像天很亮的时候,看哪里都亮。
  2. 漫反射(Diffuse):表面朝向光源的部分亮,背光部分暗,给模型立体感。
  3. 镜面反射(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 变得更有物理意义。你会发现:

  • 聚光灯不再无敌
  • distancedecay 开始发挥作用

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)

相关推荐
gaze5 分钟前
vueuse的createReusableTemplate函数实现原理
前端·vue.js
小码哥_常7 分钟前
Android开发自救指南:当大图遇上OOM,这波操作能保命!
android·前端
jsonchao9 分钟前
阿里毕业 2 个多月后,我闲着无聊做了 1 个小游戏平台
前端
支撑前端荣耀10 分钟前
十四、Cypress持续集成实践——让测试融入开发流水线
前端
今晚一定早睡11 分钟前
new操作符
前端·javascript·typescript
爱编程的喵12 分钟前
JavaScript数组高级玩法:从入门到放弃再到精通
javascript
尘心cx16 分钟前
前端-CSS-day6
前端·css
骑驴看星星a17 分钟前
定时器与间歇函数
javascript·redis·学习·mysql·oracle
红衣信17 分钟前
useContext 与 useReducer 的组合使用
前端·react.js·面试
拉不动的猪23 分钟前
针对初学者的JS八种类型实用小技巧总结
javascript·css·面试