Procedural Grid

如果想讓一個對象顯示3D模型呻待,需要2個組件 ,第一個是mesh filter。這個組件持有mesh的索引。第二個是mesh renderer炒辉,用來設(shè)定mesh如何渲染:用哪些材質(zhì)嬉挡,是否阻擋或者接受光線等等彤悔。多個材質(zhì)主要是用于導(dǎo)入類的模型噪服,同一個模型下有多個mesh組


image.png

創(chuàng)建一個點(diǎn)組成的網(wǎng)格

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Grid : MonoBehaviour {  
 public int xSize, ySize;
 }

創(chuàng)建一個空對象綁上腳本。MeshFilter的Mesh對象留空恨诱,寬高設(shè)為10媳瞪,5。給一個帶漫反射貼圖的默認(rèn)材質(zhì)


image.png

先來關(guān)注點(diǎn)的位置:點(diǎn)比格子數(shù)多一


image.png
private Vector3[] vertices;  
private void Generate () {   
    vertices = new Vector3[(xSize + 1) * (ySize + 1)];  
}

畫一個小黑球來標(biāo)記點(diǎn)的位置照宝,點(diǎn)的坐標(biāo)必須是世界坐標(biāo)蛇受。在編輯模式下也會跑到這個方法,所以先判斷空返回

private void OnDrawGizmos () {   
    if (vertices == null) 
          return;
    Gizmos.color = Color.black;   
    for (int i = 0; i < vertices.Length; i++) 
    {    
        Gizmos.DrawSphere(vertices[i], 0.1f);   
    } 
 }
image.png

為了顯示出點(diǎn)的順序厕鹃。加個協(xié)程兢仰。把點(diǎn)賦給Mesh

private Mesh mesh;
private void Awake () {  
 StartCoroutine(Generate());  
}   

private IEnumerator Generate () {  
    WaitForSeconds wait = new WaitForSeconds(0.05f);   
    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);    
               yield return wait;    
         }   
     }  
    mesh.vertices = vertices;
}

順時針畫的三角形是朝前的,逆時針的三角是向后的(下面看不見的)


正面
反面
triangles[0] = 0;   
triangles[3] = triangles[2] = 1;  
 triangles[4] = triangles[1] = xSize + 1;  
 triangles[5] = xSize + 2;
int[] triangles = new int[xSize * 6];   
for (int ti = 0, vi = 0, 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;    
    yield return wait;   
}
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;
  }

生成額外的點(diǎn)數(shù)據(jù)
因?yàn)槿切慰偸瞧降募敛辏詰?yīng)該不需要分別提供法線信息把将,但通過這種方法,可以實(shí)現(xiàn)一些技巧∫涿現(xiàn)實(shí)中頂點(diǎn)沒有法線察蹲,三角形有。通過附加自定義法線給點(diǎn)然后在三角形之間進(jìn)行插值催训,我們可以假裝我們有一個平滑彎曲的表面而不是一堆平的三角形洽议。
每點(diǎn)定義一個法線,所以我們來填充另一個向量數(shù)組漫拭〗柿澹或者我們可以要求Mesh通過三角面自己解出法線。就這么干吧嫂侍。

private void Generate () { 
    …  
   mesh.triangles = triangles;   
   mesh.RecalculateNormals(); 
 }
沒法線
有法線

接下來處理UV坐標(biāo)儿捧。注意到網(wǎng)格目前已經(jīng)有了一個標(biāo)準(zhǔn)顏色,即使它已經(jīng)使用了一個帶有漫反射貼圖的材質(zhì)挑宠。因?yàn)槲覀儧]有提供UV菲盾。所以值都是0。

vertices = new Vector3[(xSize + 1) * (ySize + 1)];   
Vector2[] uv = new Vector2[vertices.Length];   
    for (int i = 0, y = 0; y <= ySize; y++) {   
        for (int x = 0; x <= xSize; x++, i++) {   
            vertices[i] = new Vector3(x, y);   
            uv[i] = new Vector2((float)x / xSize, (float)y / ySize);   
         } 
    }  
 mesh.vertices = vertices;   mesh.uv = uv;

另一種添加細(xì)節(jié)的方法是加法線貼圖各淀。這種貼圖包含了編碼成顏色的法線向量懒鉴。但光給法線貼圖沒效果,必須先給切線向量


法線貼圖

材質(zhì)

切線的作用
法線貼圖是定義在切線空間中的碎浇。它是一個隨著物體表面起伏的3D空間临谱。這個方法允許我們將不同地方不同朝向的法線應(yīng)用到同一張貼圖中

表面向量代表了空間的上方向,但是應(yīng)該用哪種方法表示呢奴璃?它是通過切線定義的悉默。理想情況下,法線和切線的夾角是90度苟穆。它們的叉乘就是定義3D空間所需要的第三個向量抄课。實(shí)際上角度通常不是90,但結(jié)果也夠好了雳旅。

所以切線是個3D向量跟磨,但UNITY實(shí)際用了4D向量。第四個分量通常是-1或者1攒盈,用于控制切線空間的第三維的方向抵拘,要嘛朝前要嘛朝后。這個促進(jìn)了法線貼圖的鏡像型豁,通常用于3D模型中的對稱性僵蛛,比如人。Unity shader實(shí)現(xiàn)這個計(jì)算就需要我們使用-1.

由于我們用的是平面偷遗,所以所有切線簡單的指向右墩瞳。

vertices = new Vector3[(xSize + 1) * (ySize + 1)]; 
Vector2[] uv = new Vector2[vertices.Length];  
Vector4[] tangents = new Vector4[vertices.Length];  
Vector4 tangent = new Vector4(1f, 0f, 0f, -1f); 
for (int i = 0, y = 0; y <= ySize; y++) {    
    for (int x = 0; x <= xSize; x++, i++) {     
        vertices[i] = new Vector3(x, y);     
        uv[i] = new Vector2((float)x / xSize, (float)y / ySize);    
        tangents[i] = tangent;    
    }  
 }  
mesh.vertices = vertices;   
mesh.uv = uv;   
mesh.tangents = tangents; 

Mesh需要點(diǎn)坐標(biāo)和三角索引,通常也要UV坐標(biāo)氏豌,最多4組喉酌,還有切線。我們也可以添加頂點(diǎn)顏色泵喘,雖然標(biāo)準(zhǔn)SHADER沒有用它泪电。我們可以自定義使用它的SHADER。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纪铺,一起剝皮案震驚了整個濱河市相速,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鲜锚,老刑警劉巖突诬,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苫拍,死亡現(xiàn)場離奇詭異,居然都是意外死亡旺隙,警方通過查閱死者的電腦和手機(jī)绒极,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔬捷,“玉大人垄提,你說我怎么就攤上這事≈芄眨” “怎么了铡俐?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長妥粟。 經(jīng)常有香客問我审丘,道長,這世上最難降的妖魔是什么罕容? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任备恤,我火速辦了婚禮,結(jié)果婚禮上锦秒,老公的妹妹穿的比我還像新娘露泊。我一直安慰自己,他們只是感情好旅择,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布惭笑。 她就那樣靜靜地躺著,像睡著了一般生真。 火紅的嫁衣襯著肌膚如雪沉噩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天柱蟀,我揣著相機(jī)與錄音川蒙,去河邊找鬼。 笑死长已,一個胖子當(dāng)著我的面吹牛畜眨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播术瓮,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼康聂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胞四?” 一聲冷哼從身側(cè)響起恬汁,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辜伟,沒想到半個月后氓侧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脊另,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年甘苍,在試婚紗的時候發(fā)現(xiàn)自己被綠了尝蠕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡载庭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出廊佩,到底是詐尸還是另有隱情囚聚,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布标锄,位于F島的核電站顽铸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏料皇。R本人自食惡果不足惜谓松,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望践剂。 院中可真熱鬧鬼譬,春花似錦、人聲如沸逊脯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽军洼。三九已至巩螃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間匕争,已是汗流浹背避乏。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甘桑,地道東北人拍皮。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像扇住,于是被迫代替她去往敵國和親春缕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355