前言:这篇文章解释「法线贴图」如何产生。翻译自国外大神的文章

原理
法线贴图生成器首先做的是将输入图像转换为灰度图像,即使它是彩色的,这是因为颜色信息在生成过程中实际上是无用的,因此建议你在使用法线贴图生成器之前将输入图像转换为灰度,原因将在下一节中变得清晰。
想象一下,图像是一个顶点网格,每个顶点代表一个像素,每个顶点的 z 位置(高度)等于它的值(这只是一个标量而不是 RGB 矢量; 因为它是一个灰度图像)。因此我们意识到图像只是一个 2D 函数,它将值与空间中的每个点相关联,它不是连续函数,因为它仅在空间中的某些离散点上定义。我们刚刚描述的这个表面在每个顶点都有法线(就像你的网格有法线一样),那些法线就是法线贴图存储的,所以生成器的工作就是简单地计算表面的法线并在图像中对其进行编码。可以使用表面的偏导数计算法线的分量:
在公式中, 是代表着表面的函数,
是单位法向量。我在我另一篇文章中 Normal Map Generation 解释地更详细。偏导数描述了表面的梯度和方向。只要我们知道什么是对称导数(Symmetric Derivatives)就可以计算局部导数。我在另一篇回答 中介绍过。
假设我们有偏导数,我们可以使用前面的方程计算法向量分量。法线贴图将法线矢量的 分量分别存储到图像的
通道中。如果我们试图这样做,我们会遇到一个问题,图像只能存储小于 1 的正值(假设使用标准图像格式),法向量分量总是小于 1,因为它是单位向量。但是矢量分量可以是负的,表示与空间的基本矢量相反的方向。
因此我们必须找到一个方法使数据从 [-1, 1] 映射到 [0, 1]。方法如下:
在这里, 和
是红绿通道,注意我们并没有映射 z。因为它总是正的。再想想这个重新被表示的图片,它的法向量总是面向 z 轴正方向。通过使用之前的等式,我们可以得到
值放在法线贴图里面。
现在道理讲清楚了,我们开始实现了。再啰嗦一句,如果你需要更多这方面的内容可以看我另一篇文章 Normal Map Generation
实现
我们可以创建一个节点组,在给定输入图像的情况下计算和
偏导数。实现就像翻译和减法一样简单:

有关更多信息,请参阅该文章,其余的实现就像应用上面的两个方程并从各个通道创建一个图像一样简单。
最后结果

PS:
他的文章 404 了:(
我也不知道那个 F 函数是什么。。。先这样吧。卡在这里很久了。
