作用:融合两个法线向量

用法:

void InitializeFragmentNormal(inout Interpolators i){
    float3 mainNormal = UnpackScaleNormal(tex2D(_NormalMap, i.uv.xy), _BumpScale);                              // 根据平台自动对方法线贴图使用正确的解码,并缩放法线
    float3 detailNormal = UnpackScaleNormal(tex2D(_DetailNormalMap, i.uv.zw), _DetailBumpScale);                // 根据平台自动对方法线贴图使用正确的解码,并缩放法线
    i.normal = BlendNormals(mainNormal, detailNormal);                                                          // 融合法线
    i.normal = i.normal.xzy;                                                                                    // 交换z和y
}

源码:

blender官方文档_贴图

 

 

详细解析

 融合法线

将主反照率和细节反照率相乘。但不能用法线来做这件事,因为它们是向量。在归一化之前,可以先把他们平均化。

blender官方文档_blender官方文档_02

blender官方文档_贴图_03

(平均法线)

结果不是很好。主凹凸和细节凹凸都会变平。理想情况下,当其中一个平坦时,它根本不会影响另一个。

我们在这里实际上要尝试做的是结合两个高度场。平均它们没有意义。叠加它们更有意义。当添加两个高度函数时,它们的斜率(也就是它们的导数)也要相加。

我们可以从法线中提取导数吗?

之前,我们通过归一化构造了自己的法线向量

blender官方文档_缩放_04

法线贴图包含相同类型的法线,除了它们的Y和Z分量已互换。所以它们的形式是

blender官方文档_归一化_05

但是,这些法线已通过标准化过程进行了缩放。所以我们从

blender官方文档_贴图_06

开始。

s是任意比例因子。Z分量等于该因子。这意味着我们可以通过将X和Y除以Z来找到偏导数。这仅在Z为零(与垂直表面相对应)时失败。我们的凹凸远没有那么陡峭,所以不必为此担心。

一旦有了导数,就可以将它们相加,以求出总和高度场的导数。然后,我们转换回法线向量。在归一化之前,所得向量为

blender官方文档_blender官方文档_07

blender官方文档_归一化_08

blender官方文档_贴图_09

(增加导数)

这样会产生更好的结果!当组合大部分为平面的贴图时,它的效果很好。但是,合并陡峭的斜率仍然会丢失细节。另一种替代方法是泛白混合。首先,将新法线乘以 MzDz。之所以可以这样做,是因为之后无论如何都要进行归一化。这给了我们向量

blender官方文档_缩放_10

然后降低X和Y的缩放比例,得到

blender官方文档_贴图_11

这种调整会夸大X和Y分量,从而沿陡峭的坡度产生更明显的凸起。但是,当一个法线平坦时,另一个法线不会改变。

为什么称为泛白混合?

该方法由Christopher Oat在SIGGRAPH’07上首次公开描述。它用于AMD的Ruby:Whiteout演示中,因此得名。

blender官方文档_归一化_12

blender官方文档_缩放_13

(泛白混合法线,和反照率)

UnityStandardUtils包含BlendNormals函数,该函数还使用泛白混合。因此,让我们开始这个功能。它还可以标准化结果,因此我们不再需要自己做。

blender官方文档_缩放_14

BlendNormals是什么样的?

它执行与我们完全相同的计算。

blender官方文档_贴图