2018-01-28 Shader中法线变换的记录

1.从“模型空间”到“世界空间”(Object To World):

(1)方法1,使用和“顶点”到“世界”变换矩阵的“逆转置矩阵“对法线进行相同的变换,因此先得到顶点的模型到世界的变换矩阵的“逆矩阵”(Unity_WorldToObject),然后通过调换它在mul函数中的位置,得到和转置矩阵相同的矩阵乘法,由于法线是一个三维矢量,因此我们只需要街截取unity_WorldToObject的前三行前三列:

worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject))

最外侧的运算“normalize(x)”表示归一化。

(2)使用Unity内置的语法“UnityObjectToWorldNormal()”。
这是Unity5.x在中,可以通过“内置着色器”中的“Unity.cginc”中找到相关的用法,截一小段代码:

// Transforms normal from object to world space
inline float3 UnityObjectToWorldNormal( in float3 norm )
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
    return UnityObjectToWorldDir(norm);
#else
    // mul(IT_M, norm) => mul(norm, I_M) => {dot(norm, I_M.col0), dot(norm, I_M.col1), dot(norm, I_M.col2)}
    return normalize(mul(norm, (float3x3)unity_WorldToObject));
#endif
}

注释已经写的很清楚了“把法线从模型空间变换到世界空间”,里面做了个判断。如果是“统一缩放”那么这个方法用的是“UnityObjectToWorldDir()”,如果是非统一缩放,则用“normalize(mul(norm, (float3x3)unity_WorldToObject)”,这个就是和“方法1”是一模一样的。之所以这种写法,就是为了保证模型“非统一缩放”也不会得到错误的法线。
而Unity封装的这个方法,就解决了,不管模型是不是统一缩放,用这个肯定没有错。在Unity4.x和之前,是不用管是不是统一缩放的,因为当模型缩放后,unity会在背后重新生成一个模型,和缩放后的一样大,从而法线肯定不会错。但是unity5.x及以后,就必须要注意这个问题。
下面看一下在shader中,怎么使用这个方法:

normalDir = UnityObjectToWorldNormal(v.normal)

很简单的一句话。

你可能感兴趣的:(2018-01-28 Shader中法线变换的记录)