跳到主要内容
腾讯题库 · Q04

原题 Q04 · 当前收录 3 / 49

学习状态 未开始

Normal Map 空间

概念理解 normal-map · tangent-space 对应课程:PBR 与光照

面试官问

PDF 第 8 页

请说明法线贴图(Normal Map)在 Tangent Space 与 Object Space 中的区别,为何游戏引擎普遍采用 Tangent Space?(必问题,理清逻辑)

学习进度

0/9 已勾

只保存在这台浏览器;勾满 9 项即视为本题完成。

先把题目说成人话

一扇雕花门只做整体旋转时,门上的凹凸明暗应该跟着门转;把同一花纹贴到会弯的橡胶片或镜像墙砖上时,细节还要贴着每一小块表面走。现实问题不是“贴图是什么颜色”,而是贴图里保存的许多朝向箭头究竟以谁为参照。参照选错,模型一转或一弯,凹凸就会漂到错误方向。

表示表面朝向的箭头叫法线(Normal),保存许多细小朝向的纹理叫法线贴图(Normal Map)。方向相对整个模型坐标保存,叫物体空间(Object Space);方向相对每一点局部表面保存,叫切线空间(Tangent Space)。局部表面用于搬运方向的三根轴叫切线、副切线和法线组成的局部三轴(TBN)。

这是虚构教学故事,不是个人项目经历。

场景:先让问题变得看得见

同一扇雕花门有两个版本:一扇只做刚体旋转,另一扇会弯曲变形。美术还想把同一块砖纹法线复用到不同朝向的墙面上。

Tangent Space 贴图常见底色接近蓝紫色,意思是“小箭头大多沿着当前表面朝外”;采样后要先把纹理颜色还原成带正负方向的向量,再用 TBN 基变换到世界或视图空间。Object Space 贴图直接保存模型坐标中的方向,再用模型的法线矩阵变到光照空间。具体数值与矩阵关系留到画面模型成立后再对表。

(右脑)画面:在一个橡皮人偶的手臂上画满细小箭头,让每支箭头都从皮肤表面朝外。先转动整条手臂,箭头会跟着手臂一起转;再弯下手肘,弯曲处的箭头也应该贴着皮肤改变方向。如果手臂已经弯了,箭头却还固执地指向原来的地方,光照出来的凹凸就会像从皮肤上滑走。

(左脑)对表:比较对象是法线向量的编码基,而不是贴图颜色本身。刚体旋转、骨骼变形、复用和镜像 UV 后的 world/view normal debug 是观察事实与证据;“蓝紫更准、彩虹更差”只是待检假设。向量必须从纹理范围解码并归一化,T、B、N 与光照方向必须进入同一坐标空间;刚体或均匀缩放可取旋转方向后归一化,非均匀缩放或剪切则要对局部线性变换使用逆转置法线矩阵。镜像 UV 还要保留手性。小罗盘类比解释相对关系,但类比不等于烘焙器与 Unity 切线基已经一致的证明。

小明:先形成一个完整猜测

小明根据颜色判断:“蓝紫色就是 Tangent Space,彩虹色就是 Object Space,所以前者一定更准确。”

颜色确实是线索,却不是精度结论。Object Space 可以直接表达模型坐标中的完整方向,甚至少一次 TBN 变换;它的问题主要是贴图与特定模型姿态、拓扑和朝向绑定,复用和变形适应性差。

小红:把猜测放回现实检查

小红做两个反例。

第一个实验只旋转整扇刚体门。两种法线都应随模型正确旋转:Tangent Space 经 TBN 转换,Object Space 经 Object-to-World 法线矩阵转换。若这个版本旋转后光照仍停在原来的世界方向,说明实现误把模型坐标当成了 World Space。

第二个实验让门发生骨骼弯曲,并把同一法线纹理复用到另一面旋转、缩放、镜像 UV 的墙。Tangent Space 的局部凹凸会跟随变形后的 TBN;Object Space 贴图仍记录烘焙姿态中的模型方向,不会自动变成当前曲面的方向。若项目硬要支持这条路径,必须显式提供随变形更新的法线变换,不能把混合后的骨骼位置矩阵直接套到法线上:常见线性蒙皮中,混合每根骨骼的法线变换或对混合后的局部线性变换取逆转置都只是实时近似,精确曲面法线还受局部变形导数与权重变化影响。它也不能像 Tangent Space 那样随意平铺或复用。

我:用检查结果修正模型

我把可变形角色、可复用平铺材质和会更换朝向的模块资产统一为 Tangent Space,并锁定烘焙器与 Unity 使用同一套切线基约定。镜像 UV 依靠 tangent.w 的手性符号重建 Bitangent,同时检查平台的绿色通道约定。

只在完全固定、贴图专属于该网格,并且管线明确支持的特殊资产上优先考虑 Object Space;骨骼对象若采用它,必须把变形约定和近似误差一并写进资产契约。无论使用哪一种空间,刚体旋转后都要归一化,遇到非均匀缩放或剪切则应使用局部线性变换的逆转置法线矩阵,不能把位置变换直接套到法线上。

(右脑)画面修正:小明只看贴图是蓝紫色还是彩虹色,就判断谁更准确。小红先转动完整物体,再让表面弯曲、复用和翻面,真正的差别才出现:两种方向记录都能跟随刚体转动,但表面局部空间更容易随着弯曲后的皮肤和重新铺设的纹理继续工作;模型空间记录则更依赖最初那件网格和姿态。

(左脑)严格对表:Tangent Space 路径按以下数据顺序验收:采样并解码 nTSn_{TS};插值后先令 N=normalize(N)N=normalize(N),再用 T=normalize(T−N dot(T,N))T=normalize(T-N\,dot(T,N)) 把切线对 NN 正交化;将切线手性与对象变换手性(包括负缩放)合并为 ss,按 B=normalize(cross(N,T)) sB=normalize(cross(N,T))\,s 重建副切线,再用 TBN 把 nTSn_{TS} 变到光照空间。Object Space 路径在刚体或均匀缩放下可用旋转部分并归一化;存在非均匀缩放或剪切时,必须用局部线性变换的逆转置。骨骼路径还要注明采用哪种法线变形近似,不能只写“混合骨骼矩阵”。两条路径都必须通过刚体旋转测试;声称支持变形的路径还要通过弯曲、镜像 UV、负缩放与非均匀缩放测试,debug 输出与当前几何朝向一致才算通过。

老师解惑

  • Tangent Space:方向相对表面局部 TBN;适合平铺、复用、骨骼变形和不同朝向的网格。
  • Object Space:方向相对模型坐标;刚体旋转可以正确工作,但贴图通常与特定网格和烘焙姿态绑定。
  • World Space:方向相对世界坐标,才会表现为“固定在世界轴上”;它不能和 Object Space 混称。
  • TBN 基:Tangent、Bitangent、Normal 组成的局部坐标系。插值后通常要重新正交化或至少归一化。
  • 镜像 UV:会改变切线基手性;需要 tangent.w 等符号恢复正确的 Bitangent。
  • 变形边界:位置的线性混合不自动给出严格的法线变换;骨骼资产必须声明法线近似,非均匀缩放或剪切使用逆转置并重新归一化。

工具分工

  • Unity Mesh Importer:检查 Normals、Tangents、法线贴图类型及通道约定。
  • 法线 Debug Shader:分别显示 tangent、object、world normal,旋转和变形模型验证空间。
  • Frame Debugger / RenderDoc:确认实际启用的 Shader 变体和法线纹理解码,不替代空间数学检查。

记忆钩子

Object Space 跟模型走,Tangent Space 跟表面走,World Space 才跟世界走。

这是教学场景,不是目标项目的真实捕获或个人经历。

下一步:验证这条因果

让法线、高光和模型旋转始终对得上。

教学边界:它只验证这一条画面因果,不替代完整答案、项目经历或目标设备数据。

进入教学 Lab:「Normal Spaces:一根法线到底在哪个空间里」