Catlike Coding网站文章解析 -- 1.Procedural Grid
原文英文版鏈接https://catlikecoding.com/unity/tutorials/procedural-grid/,里面有每一部分的untiy工程鏈接,文章內容也更詳實。
本章內容:
- 創建一系列點
- 使用協程實現他們的擺放位置
- 定義一個由三角形組成的平面
- 自動生成法線
- 添加紋理坐標和切線
1.渲染啥
你如果想在unity中看見什么東西,那你肯定需要一個mesh。它可能是一個由其他軟件導出的3D模型或者是程序化生成的mesh。它可能是一個sprite,UI元素或者粒子特效,總之在unity里你想看到點東西你就得用mesh去渲染。
所以mesh是個啥?從概念上講,一個mesh是圖形硬件用于渲染復雜東西的一系列數據組合,它至少包括頂點的集合以及一系列三角形。三角形是最基本的2d圖形,它連接了三個點,無論mesh是什么樣,都是這些三角形組成了每個平面。
三角形平坦且邊緣直,可以完美的展示平坦平直的東西,比如一個立方體的面。帶弧度或者凹進去的平面只能通過大量小三角形近似模擬。如果這些小三角形足夠小,小于一個像素,那你對這種近似就沒有感知。但是對于實時的渲染不太可行,這些平面(圓弧的面)在某些角度看上去會有鋸齒。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Unity's default capsule, cube, and sphere, shaded vs. wireframe?
?在unity中渲染3D物體需要兩個組件mesh filter 和 mesh rendere,filter指向你想要渲染的mesh(渲染what),renderer定義如何渲染(how 怎么渲染)。
?
提供一個albedo顏色貼圖可以是最簡單便捷的方式使得mesh渲染時富有細節。通過UV坐標,可以實現貼圖的采樣從而進行渲染。
2.創建一系列頂點
?如何創建自己的mesh?
? 創建C#Grid類
using UnityEngine; using System.Collections; public class Grid : MonoBehaviour {public int xSize, ySize; }自動添加所需的component
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] public class Grid : MonoBehaviour {public int xSize, ySize; }Awake方法里調用Genrate函數
private void Awake () {Generate();}由下圖所示,對于大小橫向為x縱向為y的grid,實際需要的頂點數量是 (x+1) * (y+1)
?創建頂點數組并賦予其每個點位置
private void Generate () {vertices = new Vector3[(xSize + 1) * (ySize + 1)];for (int i = 0, y = 0; y <= ySize; y++) {for (int x = 0; x <= xSize; x++, i++) {vertices[i] = new Vector3(x, y);}}}Gizmos調試
private void OnDrawGizmos () {Gizmos.color = Color.black;for (int i = 0; i < vertices.Length; i++) {Gizmos.DrawSphere(vertices[i], 0.1f);}}Gizmos的效果(x = 10 y = 5)
3.創建Mesh?
?之后需要為mesh設置三角形片元,這里設置的值其實是之前頂點數組的索引,也就是數組的下標。
?上邊這么設置三個點,是啥也看不到的,因為這三個點在一條線上,無法組成三角形
triangles[0] = 0; triangles[1] = 1; triangles[2] = xSize + 1;這么設置組成了三角形,但是也看不到,這是因為這個順序是逆時針順序,會被判定為背面,渲染時會被剃除
順時針是正面,逆時針是反面按如下設置,我們將會得到第一個三角形
triangles[0] = 0;triangles[1] = xSize + 1;triangles[2] = 1;有了第一個三角形后,我們可以繪制兩個三角形拼成一個正方形
之后我們就可以生成每一行,完整代碼如下?
private void Awake () {Generate();}private void Generate () {GetComponent<MeshFilter>().mesh = mesh = new Mesh();mesh.name = "Procedural Grid";vertices = new Vector3[(xSize + 1) * (ySize + 1)];for (int i = 0, y = 0; y <= ySize; y++) {for (int x = 0; x <= xSize; x++, i++) {vertices[i] = new Vector3(x, y);}}mesh.vertices = vertices;int[] triangles = new int[xSize * ySize * 6];for (int ti = 0, vi = 0, y = 0; y < ySize; y++, vi++) {for (int x = 0; x < xSize; x++, ti += 6, vi++) {triangles[ti] = vi;triangles[ti + 3] = triangles[ti + 2] = vi + 1;triangles[ti + 4] = triangles[ti + 1] = vi + xSize + 1;triangles[ti + 5] = vi + xSize + 2;}}mesh.triangles = triangles;}最后效果如下:
?
4.生成其他頂點數據
法線
我們還沒有給我們生成的mesh賦予法線,默認的法線方向是(0,0,1),這并不是我們想要的。
每個Vertex(頂點)都需要設置法線,我們可以自己再創建一個數組來設置法線。還有更好的辦法,用unity提供的功能,調用mesh中的RecalculateNormals函數,它會根據之前設置好的三角形數據自動計算法線。對于某個vertex,法線的計算是對包含該vertex的所有三角形的法線取平均值,并歸一化。
有了法線才能進行光照的計算?
UV坐標
默認UV坐標都是0,所以我們必須為每個vertex頂點設置UV坐標,UV坐標范圍是0到1,所以設置方法如下
上邊的代碼不會正確的顯示結果,這是因為我們應該使用float來計算UV而不是整數除法
我們可以通過設置貼圖的tiling屬性來達到一些效果
法線貼圖
我們可以用法線貼圖來給渲染增加更多效果。關于法線貼圖的原理和技術請自行學習吧
?
?目前法線貼圖的信息是存儲在切線空間(切線空間的知識請自行學習),所以我們需要為mesh中的頂點設置切線信息。因為我們目前做出來的是一個平坦的平面,所以切線信息很好設置,平行于平面。
法線貼圖在一個平面上的效果,明明是一個平面,但是視覺上卻有凹凸起伏的感覺?
?
總結
以上是生活随笔為你收集整理的Catlike Coding网站文章解析 -- 1.Procedural Grid的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: taro-ui scrollview o
- 下一篇: Pane和Panel的区别