为了计算光照, 我们需要使用网格的"法线
". 一个表面法线是一个垂直于切线平面的向量. 简单来说, 它是一个向量, 垂直于给定顶点处的网格. 下面我们会看到一个网格, 每个顶点都有一条法线.
每个向量都指向外面, 遵循着网格的弯曲形状. 下面是另一个例子, 这次是一个简单的 2D
边沿视图:
法线贴图
(Normal Mapping
)是一个游戏编程技巧, 它允许我们渲染相同数目的多边形(例如低解析度的网格模型), 但是在计算光照时使用高解析度网格模型的法线. 这为我们带来更好的感受, 关于深度, 真实性和光滑度.
高面数网格模型或者说精雕模型的法线被编码到一个纹理贴图(即法线图)中, 当我们渲染低面数网格模型时会从片段着色器中对它进行取样. 结果如下:
注: 左侧是4百万个三角形的高模, 中间是500个三角形的低模, 右侧是在500个三角形的低模上使用法线贴图后的效果。
对法线编码和解码
我们的表面法线是单位向量, 通常位于范围 -1.0
到 1.0
之间. 我们可以通过把法线范围转换为 0.0
到 1.0
之间来把法线向量(x, y, z)
存储到一个 RGB
纹理贴图中. 下面是伪码:
Color.rgb = Normal.xyz / 2.0 + 0.5;
例如, 一个法线 (-1, 0, 1)
会被作为 RGB
编码为 (0, 0.5, 1)
. x
轴(左/右)被保存到红色通道, y
轴(上/下)被保存到绿色通道, z
轴(前/后)被保存到蓝色通道. 最终的法线图(normal map
)看起来就是下面这个样子:
一般来说, 我们使用程序来生成法线图, 而不是手动绘制.
理解法线图, 把每个通道独立出来查看会更清楚:
在绿色通道中,我们看到更亮的部分(值更接近于 1.0
) 定义了法线指向上方的区域,而更暗的区域(值更接近为 0.0
) 定义了法线指向下方的区域. 大多数的法线图会是蓝色,因为Z
轴(蓝色通道)通常指向我们(即值为 1.0
).