Unity - 从RG中解压法线贴图


环境

Unity : 2020.3.37f1
Pipeline : BRP


目的

备忘便于索引


问题

之前使用 GPA 还原一些效果的时候,发现 法线贴图的 Y 通道数值不对,感觉被 翻转了

比方说,下面是 GPA 中的法线
在这里插入图片描述

这个法线是 DX 方式的,不是 OpenGL 的,如何辨别 法线是属于 DX 还是 OpenGL 的,可以参考:快速判断OpenGL和DirectX法线的技巧


具体我们打开 PS 来查看差异
在这里插入图片描述

可总结为:

  • GL 的 凸面
    • 正X 是向右的
    • 正Y 是向上的 (绿色向上)
  • DX 的 凸面
    • 正X 是向右的
    • 正Y 是向下的 (绿色向下)

解决

我们在 BRP 管线中,可以看到类似的 解释方式
已知 normal.rg 那么 normal.z = sqrt(1 - dot(normal.rg, normal.rg))
然后如果要 scale 的话还可以这样: normal.xy *= scale

在这里插入图片描述

因此我们自己的想就可以按自己的方式来处理
不用判断 DX 或是 GL,反正我们自己限制好使用 GL 的规格,即可
这样法线贴图只使用到两个通道,然后 BA 通道还可以放其他的数据
如果是要是需要你也可以整一个参数控制 normal flipping

...
half3 raw_normal = tex2D(_BumpMap, uv);
raw_normal.y = lerp(raw_normal.y, raw_normal.y * -1, _NormalY_Flipping);
raw_normal.z = sqrt(1 - dot(raw_normal.xy, raw_normal.xy));
half3 normalWS = T2W(raw_normal, xxx);
...

最终我们还原了 GPA 的大概效果:
在这里插入图片描述


nVidia texture tools - normal map 也有类似说明

nvidia-texture-tools-exporter
在这里插入图片描述

视频直达传送门: NVIDIA_Texture_Tools_Normalmap_Overview_embed_2
在这里插入图片描述

留意:
在这里插入图片描述

这里头有将怎么计算 b 通道

b = 0.5 * sqrt(1 - (2r - 1)^2 - (2g - 1)^2 + 0.5

其中:-1~+1 的 b 为: b = sqrt(1 - (2r - 1)^2 - (2g - 1)^2

然后我们通过 val * 0.5 + 0.5 转为 0~1

所以上述公式可以看成是:b = 0.5 * b + 0.5

这个式子是来自于 单位向量公式:(x,y,z)
x^2 + y^2 + z^2 = 1


References