当前位置: 首页 > news >正文

Lightmap 存的到底是什么?从“白衣服在红灯下变红“说起

一个你可能从没想过的问题

先别急着聊技术。我问你一个生活里的问题:

一件白色的衬衫,是什么颜色的?

你大概会说"白色啊"。但真的是这样吗?

白衬衫 + 正常日光 → 你看到白色 白衬衫 + 昏暗房间 → 你看到灰色 白衬衫 + KTV红灯 → 你看到红色 白衬衫 + 全黑房间 → 你什么都看不到(黑色)

同一件白衬衫,在不同的光下,你看到的颜色完全不同。

这引出一个反直觉、但极其重要的事实:

你眼睛看到的颜色,从来都不是物体本身的颜色。
你看到的 = 物体本色 和 光 一起决定的结果。

理解了这句话,你就理解了游戏引擎里 Lightmap 的一切。这篇文章就从这里出发,把三个问题讲透:

  1. Lightmap 到底存的是什么?
  2. 为什么最终画面是"本色 × 光",而且是乘法
  3. Lightmap 里的光又是从哪来的?

一、Lightmap 存的是"光",不是"颜色"

先给结论:

Lightmap 存的是"这个点收到了多少光",不是物体是什么颜色。

这是最容易搞混的地方。一个游戏物体最终显示出来的样子,其实是两样东西合成的,它们必须分清楚:

最终画面颜色 = 物体本色 × 收到的光 └────┬────┘ └───┬───┘ 颜色贴图 Lightmap (Albedo) (光照信息) 美术画的 烘焙算的

拿一面白墙举例:

存的是什么白墙的值
颜色贴图(Albedo)物体本身是什么颜色全白,均匀一片
Lightmap它每个位置收到多少光靠灯近的亮,墙角暗

画出来是这样:

白墙本色(颜色贴图): ┌──────────┐ 到处都白,没有明暗 │██████████│ └──────────┘ Lightmap(光照): ┌──────────┐ 只记录哪亮哪暗 │▓▓▒▒░░▒▒▓▓│ 中间亮、墙角暗 └──────────┘ 两张一乘 = 你看到的画面: ┌──────────┐ 白墙上有了明暗立体感 │▓▓▒▒░░▒▒▓▓│ └──────────┘

注意:Lightmap 里根本没有"这墙是白的"这个信息。它只管"哪里亮、哪里暗"。墙是什么颜色,是颜色贴图的事。两者各管一摊。


二、为什么是"相乘",而不是"相加"?

这是全文最关键的一点。为什么最终颜色是本色乘以光,而不是加上光?

答案是:物体的"本色",本质上是一个"反射比例"。

想想物体为什么有颜色——因为它反射一部分光、吸收一部分光

白色 = 1.0 = 收到的光 100% 反射出去 灰色 = 0.5 = 收到的光 只反射 50% 黑色 = 0.0 = 收到的光 全部吸收,一点不反射

所以物体本色其实是个"折扣率",它作用在光上面:

你看到的亮度 = 收到多少光 × 反射出去的比例 = 光 × 本色

这就是为什么是乘法——本色是个比例,比例当然是用乘的。

用具体数字感受一下(光强用 0~1 表示):

白墙(本色1.0) 被强光(0.9)照: 0.9 × 1.0 = 0.9 → 明亮的白 白墙(本色1.0) 在墙角(0.2): 0.2 × 1.0 = 0.2 → 暗灰 黑墙(本色0.1) 被强光(0.9)照: 0.9 × 0.1 = 0.09 → 依然很暗

看最后一行:黑墙就算被强光直射,也亮不起来——因为它本色低,把光大都吸收了。这种效果只有乘法能表达,用加法就完全错了(加法会让黑墙被照亮变灰,不符合现实)。


三、彩色的情况:为什么白衬衫在红灯下会变红

上面是灰度,现在加上颜色。颜色是 (红, 绿, 蓝) 三个通道,相乘就是三个通道各乘各的

我们来解释开头那个"白衬衫在红灯下变红":

白衬衫 在 红灯 下

衬衫本色 = (1.0, 1.0, 1.0) ← 白:红绿蓝都 100% 反射 红灯 = (1.0, 0.0, 0.0) ← 红光:只有红,没有绿蓝 各通道相乘: 红:1.0 × 1.0 = 1.0 ✓ 有红光,衬衫也反射红 绿:1.0 × 0.0 = 0.0 ✗ 没有绿光可反射 蓝:1.0 × 0.0 = 0.0 ✗ 没有蓝光可反射 结果 = (1.0, 0, 0) = 红色 ✓

白衬衫在红灯下变红——不是衬衫变了,是它老老实实反射了唯一存在的红光。公式自动算对了。

再看一个更反直觉的:

红苹果 在 绿灯 下

苹果本色 = (1.0, 0.0, 0.0) ← 红:只反射红光 绿灯 = (0.0, 1.0, 0.0) ← 只有绿光 相乘: 红:1.0 × 0.0 = 0 ← 苹果想反射红,但环境里根本没红光! 绿:0.0 × 1.0 = 0 ← 有绿光,但苹果不反射绿(吸收掉) 蓝:0.0 × 0.0 = 0 结果 = (0, 0, 0) = 全黑!

红苹果在纯绿光下会变成黑色——这是真实的物理现象,你在实验室里能验证。而这个"本色 × 光"的公式,天然就把它算对了。


四、那 Lightmap 里的光,是从哪来的?

既然 Lightmap 存的是光,那这些光是哪来的?只有三个来源:

① 直接光——来自光源本身

太阳、灯泡,直接照过来的光。这个好理解。

② 间接光(弹射光)——来自其他表面

光打到墙上,墙会把一部分光反射出去,照亮旁边的东西。

灯 → 照亮地面 → 地面反射 → 照亮墙 → 墙再反射 → 照亮天花板 ...

这才是 Lightmap 最有价值的部分。因为间接光要追踪光线反复弹射,实时算太贵,所以提前烤进 Lightmap 最划算。

也正是间接光,解释了为什么 Lightmap 图片常常是彩色的——

插一句:为什么 Lightmap 本身是彩色的?

你如果见过 Lightmap 贴图,会发现它花花绿绿的,可能会疑惑:不是说它只存"光有多强"吗,怎么有颜色?

因为——光本身是有颜色的。

白灯照过来 → Lightmap 存白光 红霓虹灯照过来 → Lightmap 存红光 光打在红墙上弹过来 → 弹过来的光带红色!(间接光染色)

所以一面白墙如果旁边有面红墙,白墙靠近红墙的部分,在 Lightmap 里会是淡红色——因为它收到了红墙反射来的红光。

这里要再次强调那个致命的区别:

颜色贴图里的红 = "这个物体表面是红色的" Lightmap 里的红 = "有红色的光照到了这里"

两个红,完全是两回事。

③ 环境光/天空光——来自天空

光线没撞到任何物体、飞向天空的部分,会收到天空的光(比如白天蓝天的淡蓝色光)。

三者加起来,就是 Lightmap 里存的总光照:

Lightmap 存的光 = 直接光 + 间接光 + 天空光 (光源) (弹射) (天空)

五、为什么非要分开存?合并成一张不好吗?

你可能会问:既然最终是"本色 × 光",那我直接把它俩乘好,存成一张最终图片不就完了,何必分两张?

因为分开存能省下惊人的内存

如果合并存(本色×光 存成最终图): 一张墙的贴图本来能重复用在场景里 100 面墙上, 但每面墙的光照不同 → 只能给每面墙各存一张独立的最终图 → 100 张高清图 → 内存爆炸 💥 分开存(颜色一张 + 光一张): 颜色贴图:100 面墙共用同一张(本色都一样) Lightmap:只存各自的明暗,而且可以用很低的分辨率 → 内存省下一大截 ✓

而且还有个巧妙之处:光是平滑变化的(明暗过渡很缓,没有细碎纹理),所以 Lightmap 可以用很低的分辨率,放大了也不糊。而颜色贴图有细节花纹,需要高分辨率。分开存,就能各用各合适的精度,一点不浪费。


总结

用一张表收尾全文:

问题答案
Lightmap 存的是颜色吗?不是。存的是"这个点收到多少光"(光照信息)
为什么它是彩色的?因为光本身有颜色(红灯、红墙反射的红光)
光从哪来?① 直接光(光源)② 间接光(表面弹射)③ 天空光
物体本身颜色谁管?颜色贴图(Albedo),和 Lightmap 是两码事
最终画面怎么算?本色 × 收到的光(逐像素、逐 RGB 相乘)
为什么用乘法?因为本色是"反射比例",比例作用在光上就是乘
为什么分开存?颜色可共用、光可低分辨率,省内存

如果整篇文章只留一句话,那就是:

你看到的颜色,从来不是物体本身的颜色,而是"物体能反射的颜色"和"照过来的光"相乘的结果。颜色贴图管前者,Lightmap 管后者,两张图一乘,才是你在游戏里看到的画面。

全黑房间里,再白的墙也是黑的 (光=0,乘出来=0) 纯绿光下,再红的苹果也不红 (本色和光对不上,乘出来=0)

这,就是 Lightmap 的本质。


http://www.cnnetsun.cn/news/4185979.html

相关文章:

  • 基于Coze平台构建多智能体协作系统:从概念到实战部署
  • Atmosphere崩溃0x4A8怎么解决:RetroArch闪退的完整排障指南
  • 大模型技术面试核心:MoE、量化与部署实战
  • 闲鱼虚拟商品项目拆解:零成本投屏软件变现全流程
  • C#类型转换全解析:从隐式到显式,避坑指南与实战应用
  • SpringBoot集成JWT实现无状态登录认证:从原理到实战避坑指南
  • OpenSpeedy 游戏变速实战:单机游戏的节奏自己说了算
  • Java面试核心指南:并发、JVM、MySQL与Spring系统化备战
  • 大厂LLM面试核心:Transformer注意力机制QKV详解
  • LLM损失函数核心原理与面试高频考点解析
  • 2026年软件测试面试趋势与AI自动化测试实战
  • 多视角驾驶视频生成:LLM编排与统一潜在空间如何重塑自动驾驶世界模型
  • 【 福利攻略 】8 元无门槛券,奶茶、话费直接减
  • 招聘流程可视化:泳道图设计与实践指南
  • 2026年论文AI生成工具有哪些值得用?本科硕士选型参考
  • 医学影像AI亚组性能分析与适配策略实战指南
  • LLM智能体双痕迹记忆系统:实现跨会话连贯交互的工程实践
  • HDR数据集构建全流程:从硬件选型到实战应用
  • 从黑盒到掌控:Workbuddy技能本地化与Bug修复实战
  • 大语言模型中间令牌的本质:概率采样而非思考痕迹
  • Java量化系列(五十)|股票资金信息爬取全落地!搞懂资金运用+SQL+代码,精准捕捉主力动向
  • Agent智能体开发面试核心考察点与实战解析
  • 前端大数组渲染卡顿,JS大数据分片处理实战方案
  • 递归算法入门:从集合生成规则理解深度优先搜索与剪枝优化
  • 前端即时通讯实战:从协议选型到工程化落地的全链路解析
  • ScriptHookVDotNet:用 C 写 GTA V 脚本的原生函数调用插件
  • 大语言模型内存陷阱评测:MemTrapBench构建与优化实践
  • Probable-Wordlists v2资源选择指南:如何快速选对密码字典
  • miniblink49 打印完全指南:从弹窗打印到 PDF 导出
  • 基于OpenClaw构建本地AI投研大脑:从部署到实战的完整指南