您現在的位置是:網站首頁> 內容頁

手動創建Mesh及相關理論知識

  • 永利皇宮4233con網站
  • 2019-07-03
  • 433人已閱讀
簡介創建Mesh這篇教程說的非常清楚.[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]publiccl

創建Mesh

這篇教程說的非常清楚.

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] public class CodeMeshTriangle : MonoBehaviour { public Transform p0; public Transform p1; public Transform p2; private void Generate() { GetComponent<MeshFilter>().mesh = mMesh = new Mesh(); var vertices = new[] {p0.localPosition, p1.localPosition, p2.localPosition}; var triangles = new[] {0, 1, 2}; mMesh.vertices = vertices; mMesh.triangles = triangles; } }

構建一個Mesh只需要兩部分,一個是頂點坐標(vertices),一個是由頂點坐標構成的三角形(triangles)

需要注意就是其正反面,順時針(clockwise)正面,逆時針(Counter-clockwise)反面

UV映射及Normal映射

教程前半部分很好理解,比較讓我困惑的是后半部分關于NormalMap中TBN(Tangent,Bitangent,Normal)的闡述.

NormalMap的含義

首先要說的是什么是NormalMap,官網解說的非常清楚了.

普通Mesh

加入NormalMap

{% note success %}each pixel in the texture of the normal map (called a texel) represents a deviation in surface normal direction away from the “true” surface normal of the flat (or smooth interpolated) polygon.{% endnote %}

Normal映射及TBN

最讓我不理解的是教程中關于切線(tangents)的解釋. 他直接說到

As we have a flat surface, all tangents simply point in the same direction,which is to the right.

然后直接給出代碼

Vector4 tangent = new Vector4(1f, 0f, 0f, -1f);

讓人不明所以,不知道他這個為啥直接就point了right.

不過搞清楚這點要有幾個預備知識.

首先是UV映射. 可以看Y2B上的這個視頻,

沒有涉及到太底層的數學推導,感性的認知UVMaping就是

{% note success %}給定UV中的一個三角形U(三個點分別為U1,U2,U3) => 通過某種方法映射到 => 模型中的三角形P(P1,P2,P3){% endnote %}

這個視頻有開了一個頭,但是也沒具體講. 不過具體的映射方法,應該是和線性插值有關,沒有細研究

可以用線性插值,雙線性插值,Trilinear,Bilinear 作為Key搜搜看.

不過重點是下面這張圖

個人理解,不一定對. 無論UV映射也好,Normal映射也好. 都需要將貼圖首先旋轉到與需要映射的三角形相同的一個角度. 也就是對UV圖,Normal圖的坐標系有旋轉

如圖,左邊的P"三角形 和右邊的P三角形 就不在一個平面. 相應的做UV時候,其坐標軸也發生的旋轉.

而這個旋轉的角度 從某種角度來說就是TBN

原因可以看OpenGL的教程

選定Normal后

垂直與該Normal的向量有很多

為了方便計算,所以選擇和和紋理空間對齊方向

結合我自己畫的那個圖,也就是說 紋理空間的方向就是P"三角形所在的那個坐標系. 這個坐標系也就是UV的坐標系,也是NormalMap的切線(Tangent)和副切線(Bitangent)方向.

至于這個坐標系的求出

給定UV中的一個三角形U(三個點分別為U1,U2,U3) => 通過某種方法映射到 => 模型中的三角形P(P1,P2,P3)

我是理解為,給出了UV上的三個點,然后給出模型上的三個點,Unity已經就幫我們算出來了.(通過數學推導肯定是可以算出來的,我沒有細研究).

所以我理解的設置NormalMap流程應該是,設定好UV,然后給定Normal方向,最后通過Mesh.RecalculateTangents重新計算出TB兩個方向,而不是反過來直接給定了Vector4 tangent = new Vector4(1f, 0f, 0f, -1f);

不過直接給定Tangent角度現在想想似乎也可以理解. 教程中的Mesh角度和我自己畫的圖中右側的正方形一樣,此時UV圖面沒有任何旋轉,(1,0,0)也就是其x軸方向.

完整代碼:

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] public class CodeMeshTriangle : MonoBehaviour { public Transform p0; public Transform p1; public Transform p2; private Mesh mMesh; private Vector3[] mVertices; private Vector3[] mNormals; private void Update() { Generate(); } private void Generate() { GetComponent<MeshFilter>().mesh = mMesh = new Mesh(); var normal = new Vector30, -1); mVertices = new[] {p0.localPosition, p1.localPosition, p2.localPosition}; mNormals = new[] {normal, normal, normal}; var triangles = new[] {0, 1, 2}; Vector2[] uv = new Vector2[3]; uv[0] = new Vector20); uv[1] = new Vector21); uv[2] = new Vector20); mMesh.vertices = mVertices; mMesh.triangles = triangles; mMesh.uv = uv; mMesh.normals = mNormals; mMesh.RecalculateTangents(); } }

文章評論

Top 3d胆码