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)

相关推荐
Ice_Sugar_711 分钟前
CSS:BFC
前端·css
林太白15 分钟前
Vue3 导入导出
前端
_Kayo_29 分钟前
JS深拷贝 浅拷贝、CSS垂直水平居中
开发语言·前端·javascript
key_Go40 分钟前
18.WEB 服务器
服务器·前端·firefox
碎像1 小时前
uni-app实战教程 从0到1开发 画图软件 (学会画图)
前端·javascript·css·程序人生·uni-app
Hilaku1 小时前
从“高级”到“资深”,我卡了两年和我的思考
前端·javascript·面试
WebInfra2 小时前
Rsdoctor 1.2 发布:打包产物体积一目了然
前端·javascript·github
用户52709648744902 小时前
SCSS模块系统详解:@import、@use、@forward 深度解析
前端
兮漫天2 小时前
bun + vite7 的结合,孕育的 Robot Admin 【靓仔出道】(十一)
前端·vue.js
xianxin_2 小时前
CSS Text(文本)
前端