S03 UnpackNormal函数解析

UnpackNormal(fixed4 packednormal):对法线纹理进行采样。以UnpackNormal方法来说,它最主要的也就是packednormal.xyz * 2 – 1,要解释这个,就必须讲到法线纹理的生成。法线纹理是把模型的法线信息存到图片中去,每条法线的x,y,z对应的存到每个像素的r,g,b中。每条法线里的每个数值都是一个[-1,1]的闭合区间里,像素的每个数值则都是在[0,255]中,(n + vec3(1.0,1.0,1.0)) * (255.0 / 2.0),每个法线向量,经过加上 vec3(1.0,1.0,1.0)。变成[0,2]的闭合区间里,然后除以2,再乘以255,发现向量,就会转换成了[0,255]里的数值。这也是上述那条公式的由来。至于法线纹理如何生成,有兴趣的可以详细了解一下这个算法,各个软件的生成算法不一样,最终得到的法线纹理也不一样。但是纹理里的数据,肯定是符合规范的法线纹理数据,可以在shader中使用。另外一个方法UnpackNormalDXT5nm ,则是一个压缩法线纹理后的方法。大家都知道,法线是一个单位向量,也就是它的长度是1,所以只需要知道x,y的数值,是可以计算得到z的数值的,z=1-(x+y)的平方。这样就可以减少贴图的大小,减少GPU的数据传输量。
参考链接:https://my.oschina.net/u/3939659/blog/1923884

我们先来看一下官方的代码:

inline fixed3 UnpackNormal(fixed4 packednormal)
{
#if defined(SHADER_API_GLES)  defined(SHADER_API_MOBILE)
    return packednormal.xyz * 2 - 1;
#else
    fixed3 normal;
    normal.xy = packednormal.wy * 2 - 1;
    normal.z = sqrt(1 - normal.x*normal.x - normal.y * normal.y);
    return normal;
#endif
}

首先呢,我们都知道法线是一个三维向量,其每个分量的范围都是(-1,1),但在我们存储的法线图中每个通道的范围是(0,1),这其中存在一个转换关系。以R通道分量为例:

所以逆过程就是先乘以2再加上1

再者,Unity对法线贴图的压缩算法采用的格式被称为DXT5nm,这种格式的突出特点是利用A通道存储x分量,利用G通道存储y分量,因为这两个通道的bit位数最多(RGBA分别为5,6,5,8)。所以需要我们反映射,至于Z分量,由于法线向量是单位向量,所以我们可以利用几何关系求得Z分量。

你可能感兴趣的:(S03 UnpackNormal函数解析)