Unity Shader中一些知識點記錄

前言

最近在實現投影圖片到模型上的效果的時候,掌握了一些知識點,特此記錄,供以後參考。

知識點

空間座標轉換

1.用矩陣轉換向量時,被轉換的向量維度應與矩陣相同,比如模型空間轉世界空間:
錯誤代碼:

float3 pos = float3(x, y, z);
pos = mul(unity_ObjectToWorld, pos);

正確代碼:

float3 pos = float3(x, y, z);
pos = mul(unity_ObjectToWorld, float4(pos, 1)).xyz;

求某向量到平面的投影向量

已知:
1.向量vec
2.平面法向量n
算法步驟:
1.歸一化平面法向量n1 = normalize(n)
2.計算vec在法向量上的投影vec1 = n1 * dot(n1, vec)
3.vec - vec1即爲所求

構造UV的變換矩陣

注意點:
1.uv是二維的,所以構造的矩陣是float3x3
2.uv本身是[0, 1],而我們變換一般是以中心點爲基準,所以應先變換到[-0.5, 0.5]
3.縮放因子應使用倒數
代碼:

// 參數1爲目標uv
// 參數2爲控制參數,以四維向量表示,[x, y, z, w]=[橫向平移, 縱向平移, 旋轉, 縮放]
float2 TransformUV(float2 uv, float4 transformParam)
{
    float2 finalUV = uv - float2(.5, .5);
    float rot = radians(transformParam.z);
    float scale = max(1 / transformParam.w, 0);
    float sinVal = sin(rot) * scale;
    float cosVal = cos(rot) * scale;
    float3x3 myMatrix = float3x3(
        cosVal, -sinVal, 0,
        sinVal, cosVal, 0,
        0, 0, 1 
    );

    finalUV = mul(myMatrix, float3(finalUV + transformParam.xy,1)).xy;
    finalUV += float2(.5, .5);
    return finalUV;
}

矩陣

1.shader中的矩陣按可按索引獲取座標系的各軸向量,比如:

UNITY_MATRIX_V[0].xyz --> 攝像機x軸在世界空間下的值
UNITY_MATRIX_V[1].xyz --> 攝像機y軸在世界空間下的值
UNITY_MATRIX_V[2].xyz --> 攝像機z軸在世界空間下的值

2.c#中的Matrix的索引排列如下:
0481215913261014371115 \begin{matrix} 0 & 4 & 8 & 12\\ 1 & 5 & 9 & 13\\ 2 & 6 & 10 & 14\\ 3 & 7 & 11 & 15\\ \end{matrix}
3.Transform的LocalToWorld矩陣第四列前三行即該transform的世界座標值,比如:
0481215913261014371115 \begin{matrix} 0 & 4 & 8 & 12\\ 1 & 5 & 9 & 13\\ 2 & 6 & 10 & 14\\ 3 & 7 & 11 & 15\\ \end{matrix}
上面矩陣中的(12, 13, 14)即世界座標值
4.下方文字引用自這裏
在Vertex Function函數中,將模型空間的頂點轉換到投影空間, o.pos = mul(UNITY_MATRIX_MVP, v.vertex); 理解爲矩陣採用左乘,頂點向量是列向量,使用齊次座標得到4X1的矩陣.

將法向量轉到世界空間

頂點從模型空間轉換到世界座標空間只需要乘以世界轉換矩陣即可,但是頂點的法向量卻不能通過直接乘以這個矩陣將其變換到世界空間。原因是世界矩陣不僅包含旋轉,還有可能包含着縮放操作,如果模型被不成比例的縮放,在不同方向上會有不同程度的拉伸或者壓縮,頂點的座標會因而伸縮,但是如果對法向量進行同樣的伸縮,那麼變化後的法向量將不再垂直於對應的表面。因此對應沒有縮放或等比縮放的世界轉換矩陣,可以直接採用相同的轉換矩陣作爲法向量的變換矩陣。

對於法向量來講,只有方向,對於平移不起任何作用,如果我們採用_Object2World,那麼它的旋轉和縮放都進行了變換,我們不想讓它的縮放進行變換。我們就要構造新的矩陣M,屏蔽掉它的縮放,但是保留它的旋轉。現在將_Object2World的逆矩陣_World2Object轉置就得到M矩陣了。

float3 normalDirection = normalize( mul(float4(v.normal,0.0),_World2Object)).xyz; 本來應該是mul((float4(v.normal,1.0),_World2Object的轉置);

關於轉置,可以變換矩陣和向量相乘的順序,這樣就相當於和轉置矩陣相乘了。

3D模型相關

1.一個模型可使用多套UV, 一套UV可用於多套模型,這是在3D軟件端操作的;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章