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 - 面光源(广告灯箱专用)

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

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


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

光照计算三大成分:

  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 变得更有物理意义。你会发现:

  • 聚光灯不再无敌
  • 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)

相关推荐
子兮曰5 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万5 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋5 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁5 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄5 天前
JavaScript 隐式全局变量解析
javascript
汉堡大王95275 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大5 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师5 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端