1.從“模型空間”到“世界空間”(Object To World):
(1)方法1,使用和“頂點”到“世界”變換矩陣的“逆轉(zhuǎn)置矩陣“對法線進行相同的變換,因此先得到頂點的模型到世界的變換矩陣的“逆矩陣”(Unity_WorldToObject)愚战,然后通過調(diào)換它在mul函數(shù)中的位置劣纲,得到和轉(zhuǎn)置矩陣相同的矩陣乘法蠕啄,由于法線是一個三維矢量慨亲,因此我們只需要街截取unity_WorldToObject的前三行前三列:
worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject))
最外側(cè)的運算“normalize(x)”表示歸一化。
(2)使用Unity內(nèi)置的語法“UnityObjectToWorldNormal()”狰贯。
這是Unity5.x在中也搓,可以通過“內(nèi)置著色器”中的“Unity.cginc”中找到相關(guān)的用法,截一小段代碼:
// 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
}
注釋已經(jīng)寫的很清楚了“把法線從模型空間變換到世界空間”涵紊,里面做了個判斷傍妒。如果是“統(tǒng)一縮放”那么這個方法用的是“UnityObjectToWorldDir()”,如果是非統(tǒng)一縮放摸柄,則用“normalize(mul(norm, (float3x3)unity_WorldToObject)”颤练,這個就是和“方法1”是一模一樣的。之所以這種寫法驱负,就是為了保證模型“非統(tǒng)一縮放”也不會得到錯誤的法線嗦玖。
而Unity封裝的這個方法,就解決了跃脊,不管模型是不是統(tǒng)一縮放宇挫,用這個肯定沒有錯。在Unity4.x和之前酪术,是不用管是不是統(tǒng)一縮放的器瘪,因為當模型縮放后,unity會在背后重新生成一個模型,和縮放后的一樣大娱局,從而法線肯定不會錯。但是unity5.x及以后咧七,就必須要注意這個問題衰齐。
下面看一下在shader中,怎么使用這個方法:
normalDir = UnityObjectToWorldNormal(v.normal)
很簡單的一句話继阻。