Procedural Grid 程序網(wǎng)格

本文轉(zhuǎn)自

Catlike Coding

Unity C# Tutorials

https://catlikecoding.com/unity/tutorials/procedural-grid/

Create a grid of points.? ? ? 創(chuàng)建一個點的網(wǎng)格

Use a coroutine to analyze their placement.? 使用?coroutine?來分析網(wǎng)格的布局

Define a surface with triangles.? 用三角形定義一個面

Automatically generate normals.?自動生成?法線

Add texture coordinates and tangents.?添加紋理坐標(biāo)和三角形

In this tutorial we'll create a simple grid of vertices and triangles.在這篇指導(dǎo)中我們將創(chuàng)建一個由定點和三角形組成的簡單網(wǎng)格

????This tutorial assumes that you are familiar with the basics of Unity scripting. See?Clock?for these basics.?Constructing a Fractal?provides an introduction to coroutines. This tutorial has been made for Unity 5.0.1 and up.

這個教程假定你已經(jīng)熟悉基本的Unity腳本.?點這學(xué)習(xí)基礎(chǔ)知識.?構(gòu)建分形這一節(jié)課講解了coroutines. 這個教程使用Unity5.0.1?或?更高版本.


Beneath complex appearance lies simple geometry. 看似復(fù)雜的表面下隱藏著簡單的幾何圖形

Rendering Things? 渲染物體

If you want to visualize something in Unity, you use a mesh. It could be a 3D model exported from another program. It could be a procedurally generated mesh. It could be a sprite, UI element, or particle system, for which Unity uses meshes as well. Even screen effects are rendered with a mesh.

如果你想在Unity可視化一些東西,?你需要用到mesh.?它可能是由其他程序?qū)С龅?D模型.?也可能是由程序生成的mesh.?要么是一個Sprite, UI元素?或者?粒子系統(tǒng).?就算是?屏幕效果也是由一個mesh渲染的.

So what is a mesh? Conceptually, a mesh is a construct used by the graphics hardware to draw complex stuff. It contains at least a collection of vertices that define points in 3D space, plus a set of triangles – the most basic 2D shapes – that connect these points. The triangles form the surface of whatever the mesh represents.

那么mesh是什么捏?? 從概念上來說,?mesh是一個結(jié)構(gòu)?用于圖形硬件繪制復(fù)雜的東西. 它至少包含一組頂點,用于定義3D空間中的點, 以及一組連接這些點的三角形 - 最基本的2D形狀.? 這些三角形構(gòu)成的網(wǎng)格組成了可以表示任何物體的表面

As triangles are flat and have straight edges, they can be used to perfectly visualize flat and straight things, like the faces of a cube. Curved or round surfaces can only be approximated by using many small triangles. If the triangles appear small enough – no larger than a single pixel – then you won't notice the approximation. Typically that's not feasible for realtime performance, so the surfaces will always appear jagged to some degree.

因為三角形是平的并且邊是直的,?他們可以用來完美的可視化 平直 的東西,?比如cube的表面.?弧形或圓形表面只能用許多小三角形近似的表示. 通常屯蹦,這對于運行時性能來說不可行,?所以表面總是會出現(xiàn)一定程度的鋸齒。

Unity's default capsule, cube, and sphere, shaded vs. wireframe.


If you want to have a game object display a 3D model, it needs to have two components. The first is a mesh filter. This component holds a reference to the mesh you wish to show. The second is a mesh renderer. You use it to configure how the mesh is rendered. Which material should be used, whether it should cast or receive shadows, and so on.

如果你想要一個game object顯示3D模型,需要2個組件.?第一個是mesh?filter,?此組件包含對要顯示的網(wǎng)格的引用迂求。第二個是mesh?renderer,?可以配置它來決定怎么樣對mesh進(jìn)行渲染 (應(yīng)該使用哪一種材質(zhì)凌盯,是否應(yīng)該投射或接收陰影砸西,等等)。

Unity's default cube game object.? ????Unity默認(rèn)的Cube?game?object

Why is there an array of materials??????為什么有一個material數(shù)組?

A mesh renderer can have multiple materials. This is mostly used for rendering meshes that have multiple separate triangle sets, know as sub-meshes. These are mostly used with imported 3D models and won't be covered in this tutorial.

mesh?renderer?可以有多個material.?這主要用于渲染具有多個單獨三角形集合的網(wǎng)格走芋,稱為子網(wǎng)格挖函。這些大多與導(dǎo)入的3D模型一起使用,本教程不會介紹肉拓。

You can completely change the appearance of a mesh by adjusting its material. Unity's default material is simply solid white. You can replace it with your own by creating a new material asset via?Assets / Create / Material?and dragging it onto your game object. New materials use Unity's Standard shader by default, which gives you a set of controls to tweak how your surface behaves visually.

通過調(diào)整mesh的material残揉,你可以完全改變它的外觀.?Unity默認(rèn)材質(zhì)是純白色.? 你可以新建一個新的material?通過點擊?Assets / Create / Material?并拖動它到你的GameObject來替換material.?新的Material使用默認(rèn)的Standard?shader. 它提供了一組控件來微調(diào)表面的視覺表現(xiàn)眶痰。

A quick way to add lots of detail to your mesh is by providing an albedo map. This is a texture that represents the basic color of a material. Of course we need to know how to project this texture onto the triangles of the mesh. This is done by adding 2D texture coordinates to the vertices. The two dimensions of texture space are referred to as?U?and?V, which is why they're know as UV coordinates. These coordinates typically lie between?(0, 0)?and?(1, 1), which covers the entire texture. Coordinates outside that range are either clamped or cause tiling, depending on the texture settings.

給網(wǎng)格添加大量細(xì)節(jié)的一個快速方法是提供反照率圖.?這是一個紋理因宇,代表了材質(zhì)的基本顏色。當(dāng)然饲化,我們需要知道如何將這個紋理投射到網(wǎng)格的三角形上。這是通過向頂點添加2D紋理坐標(biāo)來完成的缸浦。紋理空間的二個維度被稱為U和V泣栈,這就是為什么它們被稱為UV坐標(biāo)薪缆。這些坐標(biāo)通常位于(0,0)和(1,1)之間,它們覆蓋了整個紋理。超出這個范圍的坐標(biāo)要么被clamp沧侥,要么導(dǎo)致Tiling,這取決于紋理設(shè)置。


A UV test texture applied to Unity's meshes.


2. Creating a Grid of Vertices? 創(chuàng)點頂點網(wǎng)格

So how do you make your own mesh? Let's find out, by generating a simple rectangular grid. The grid will consist of square tiles – quads – of unit length. Create a new C# script and turn it into a grid component that has a horizontal and vertical size.

那么如何制作自己的網(wǎng)格呢? 讓我們找到答案,?讓我們通過生成一個簡單的矩形網(wǎng)格來找到答案。網(wǎng)格將由單位長度的方形Tiles組成。

usingUnityEngine;

usingSystem.Collections;

public?class?Grid:MonoBehaviour

{

public?int?xSize, ySize;

}

When we add this component to a game object, we need to give it a mesh filter and mesh renderer as well. We can add an attribute to our class to have Unity automatically add them for us.

當(dāng)我們將這個組件添加到游戲?qū)ο髸r翘骂,我們需要給它一個mesh filter和?mesh renderer。我們可以為我們的類添加一個attribute,讓Unity自動添加他們.

[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]

public?class?Grid:MonoBehaviour

{

public?int?xSize, ySize;

}

Now you can create a new empty game object, add the grid component to it, and it will have the other two components as well. Set the material of the renderer and leave the filter's mesh undefined. I set the grid's size to 10 by 5.

現(xiàn)在厂汗,您可以創(chuàng)建一個新的空游戲?qū)ο笾梗袵rid?組件添加到它上面,并且它還將擁有另外兩個組件扁藕。設(shè)置渲染器的材質(zhì)并保持filter的網(wǎng)格未定義。我將網(wǎng)格的大小設(shè)置為10×5呼畸。

A grid object.

We generate the actual mesh as soon as the object awakens, which happens when we enter play mode.

進(jìn)入play mode時, 當(dāng)對象一醒來瞬痘,我們就會生成實際的網(wǎng)格

private?void?Awake()?

{

Generate();

}

Let's focus on the vertex positions first and leave the triangles for later. We need to hold an array of 3D vectors to store the points. The amount of vertices depends on the size of the grid. We need a vertex at the corners of every quad, but adjacent quads can share the same vertex. So we need one more vertex than we have tiles in each dimension.

讓我們先關(guān)注頂點位置津辩,然后把三角形放在后面蚜印。我們需要持有一個3D向量數(shù)組來存儲點楼熄。而其需要每個四邊形的角上有一個頂點缕粹,但是相鄰的四邊形可以共享同一個頂點。所以我們需要比每個維度中的瓦片多一個頂點。(x y 軸 上的頂點都比小格子多一個)

(#x+1)(#y+1)

Vertex and quad indices for a 4 by 2 grid. 一個4×2網(wǎng)格的頂點和四個索引。

private?Vector3[] vertices;

private?void?Generate ()?

{

vertices =?new?Vector3?[(xSize +1) * (ySize +1)];

}

Let's visualize these vertices so we can check that we position them correctly. We can do so by adding an?OnDrawGizmos?method and drawing a small black sphere in the scene view for every vertex.

讓我們把這些頂點可視化這樣我們就可以檢查它們的位置是否正確扛吞。我們可以添加一個OnDrawGizmos方法做院,并在場景中為每個頂點繪制一個小黑球屈雄。

private?void?OnDrawGizmos()?

{

????Gizmos.color =?Color.black;

? ??for(inti =0; i < vertices.Length; i++)

?????{

????????Gizmos.DrawSphere(vertices[i],0.1f);

????}

}

What are gizmos?? 什么是gizmos?

This will produce errors when we are not in play mode, because?OnDrawGizmos?methods are also invoked while Unity is in edit mode, when we don't have any vertices. To prevent this error, check whether the array exists and jump out of the method if it isn't.

這樣會產(chǎn)生錯誤因為OnDrawGizmos可以在編輯器模式下調(diào)用. 為了防止錯誤,檢查數(shù)組是否存在, 如果為null就跳出該方法

private?void?OnDrawGizmos()?

{

? ??if(vertices ==null)?

? ?{

? ??????return;

????}…

}

A gizmo.

While in play mode, we see only a single sphere at the origin. This is because we haven't positioned the vertices yet, so they all overlap at that position. We have to iterate through all positions, using a double loop.

在游戲模式中,我們只能在原點看到一個球體笛钝。這是因為還沒有為頂點設(shè)置position,所以它們都在那個位置重疊。我們需要使用雙層循環(huán)遍歷所有位置。

private?void?Generate ()?

{

????vertices =newVector3[(xSize +1) * (ySize +1)];

? ??for(inti =0, y =0; y <= ySize; y++)

?????{

? ??????for(intx =0; x <= xSize; x++, i++)

?????????{

????????????vertices[i] =newVector3(x, y);

????????}

? ? ? ?}

}

A grid of vertices.

We now see the vertices, but the order in which they were placed isn't visible. We could use color to show this, but we can also slow down the process, by using a coroutine. This is why I included?using?System.Collections?in the script.

我們現(xiàn)在看到頂點跪呈,但它們的放置順序是不可見的。我們可以使用顏色來顯示這個,但是我們也可以通過使用協(xié)程來減慢這個過程奴紧。

private?void?Awake()?

{?

StartCoroutine(Generate());

}

private?IEnumerator?Generate ()?

{

WaitForSeconds?wait =?new?WaitForSeconds(0.05f);

vertices =newVector3[(xSize +1) * (ySize +1)];

for(inti =0, y =0; y <= ySize; y++)

?{

for(intx =0; x <= xSize; x++, i++)

?{

vertices[i] =newVector3(x, y);

yieldreturnwait;

}

}

}

Watching the vertices appear.

unitypackage


3. Creating the Mesh? 創(chuàng)建Mesh

Now that we know that the vertices are positioned correctly, we can deal with the actual mesh. Besides holding a reference to it in our own component, we must also assign it to the mesh filter. Then once we dealt with the vertices, we can give them to our mesh.

現(xiàn)在我們知道頂點位置正確沫浆,我們可以處理實際的網(wǎng)格。除了在我們自己的component中保存對它的引用之外,我們還必須將它分配給mesh filter躬审。然后蹬碧,一旦處理了頂點,就可以將它們提供給mesh渤闷。


private?Mesh?mesh;

private?IEnumerator?Generate ()?

{

WaitForSeconds?wait =newWaitForSeconds(0.05f);

GetComponent<MeshFilter>().mesh =?mesh?=?new?Mesh();

mesh.name ="Procedural Grid";

vertices =newVector3[(xSize +1) * (ySize +1)];

mesh.vertices = vertices;

}


Mesh appears in play mode.

We now have a mesh in play mode, but it doesn't show up yet because we haven't given it any triangles. Triangles are defined via an array of vertex indices. As each triangle has three points, three consecutive indices describe one triangle. Let's start with just one triangle.

我們現(xiàn)在在play?mode已經(jīng)有了一個網(wǎng)格肩碟,但它還沒有顯示出來,因為我們沒有給它任何三角形脑漫。三角形是通過頂點數(shù)組的index定義的吨拍。由于每個三角形有三個點密末,三個連續(xù)的index描述一個三角形。 讓我們從一個三角形開始吧追城。

private?IEnumerator?Generate ()?

{

????…

? ??int[] triangles =newint[3];

????triangles[0] =0;

????triangles[1] =1;

????triangles[2] =2;

????mesh.triangles = triangles;

}

We now have one triangle, but the three points that we are using all lie in a straight line. This produces a degenerate triangle, which isn't visible. The first two vertices are fine, but then we should jump to the first vertex of the next row.

現(xiàn)在我們有了一個三角形,但是這3個點組成的線段都在一條直線上.?這會產(chǎn)生一個不可見的退化三角形(退化三角形是指面積為零的三角形)戏锹。前兩個頂點沒問題锦针,但是我們應(yīng)該跳到下一行的第一個頂點奈搜。

triangles[0] =0;

triangles[1] =1;

triangles[2] =xSize +1;

This does give us a triangle, but it's visible from only one direction. In this case, it's only visible when looking in the opposite direction of the Z axis. So you might need to rotate the view to see it.

這確實給了我們一個三角形,但它只能從一個方向可見秋秤。在這種情況下绍哎,它只在Z軸的相反方向上可見蛇摸。因此,您可能需要旋轉(zhuǎn)視圖來查看它抠藕。

Which side a triangle is visible from is determined by the orientation of its vertex indices. By default, if they are arranged in a clockwise direction the triangle is considered to be forward-facing and visible. Counter-clockwise triangles are discarded so we don't need to spend time rendering the insides of objects, which are typically not meant to be seen anyway.

從哪個角度看三角形是可見的取決于它的頂點索引的方向盾似。默認(rèn)情況下零院,如果它們按順時針方向排列撰茎,則認(rèn)為三角形是正向且可見的龄糊。逆時針三角形被丟棄炫惩,所以我們不需要花時間渲染對象的內(nèi)部他嚷,這些對象通常不會被看到蟋字。

The two sides of a triangle.

So to make the triangle appear when we look down the Z axis, we have to change the order in which its vertices are traversed. We can do so by swapping the last two indices.

為了讓三角形出現(xiàn)在Z軸下方鹊奖,我們必須改變頂點遍歷的順序。我們可以交換最后兩個指標(biāo)两蟀。

triangles[0] =0;

triangles[1] =xSize +1;

triangles[2] =1;

The first triangle.

We now have one triangle that covers half of the first tile of our grid. To cover the entire tile, all we need is a second triangle.

現(xiàn)在我們有了一個三角形赂毯,它覆蓋了網(wǎng)格第一塊tile的一半党涕。為了覆蓋整個tile,我們需要第二個三角形肥荔。

int[] triangles =new?int[6];

triangles[0] =0;

triangles[1] = xSize +1;

triangles[2] =1;

triangles[3] =1;

triangles[4] = xSize +1;

triangles[5] = xSize +2;

A quad made with two triangles.

As these triangles share two vertices, we could reduce this to four lines of code, explicitly mentioning each vertex index only once.

triangles[0] =0;triangles[3] = triangles[2] =1;triangles[4] = triangles[1] = xSize +1;triangles[5] = xSize +2;

The first quad.

We can create the entire first row of tiles by turning this into a loop. As we're iterating over both vertex and triangle indices, we have to keep track of both. Let's also move the yield statement into this loop, so we no longer have to wait for the vertices to appear.

我們可以通過將其轉(zhuǎn)換為循環(huán)來創(chuàng)建整個第一行圖塊。 當(dāng)我們迭代頂點和三角形索引時缸棵,我們必須跟蹤兩者堵第。 讓我們也將yield語句移動到這個循環(huán)中,這樣我們就不必再等待頂點出現(xiàn)了针余。

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;

? ??yieldreturn?wait;

}

The vertex gizmos now immediately appear, and the triangles all appear at once after a short wait. To see the tiles appear one by one, we have to update the mesh each iteration, instead of only after the loop.

頂點gizmos現(xiàn)在立即出現(xiàn)圆雁,三角形在短時間的等待后立即出現(xiàn)伪朽。要看到這些塊一個一個地出現(xiàn),我們必須在每次迭代中更新網(wǎng)格窖剑,而不僅僅是在循環(huán)之后西土。

mesh.triangles = triangles;

yield?return?wait;

Now fill the entire grid by turning the single loop into a double loop. Note that moving to the next row requires incrementing the vertex index by one, because there's one more vertex than tiles per row.

現(xiàn)在跳昼,通過將單個循環(huán)變?yōu)殡p循環(huán)來填充整個網(wǎng)格庐舟。注意挪略,移動到下一行需要將頂點索引增加1個杠娱,因為每一行比tiles多一個頂點。

int[] triangles =new?int[xSize *ySize *6];

for(int?ti =0, vi =0,y =0; y < ySize; y++, vi++)

?{

? ??for(intx =0; x < xSize; x++, ti +=6, vi++)?

????{…}

}


Filling the entire grid.

As you can see, the entire grid is now filled with triangles, one row at a time. Once you're satisfied with that, you can remove all the coroutine code so the mesh will be created without delay.

正如您所看到的室叉,整個網(wǎng)格現(xiàn)在是由三角形填充的茧痕,每次一行÷眨現(xiàn)在你可以刪除所有的協(xié)程代碼舀患,這樣網(wǎng)格就可以無延遲地創(chuàng)建聊浅。

4 . Generating Additional Vertex Data? 生成附加的頂點數(shù)據(jù)

Our grid is currently lit in a peculiar way. That's because we haven't given any normals to the mesh yet. The default normal direction is?(0, 0, 1)?which is the exact opposite of what we need.

我們的網(wǎng)格目前以一種奇怪的方式照亮。那是因為我們還沒有給出網(wǎng)格的法線朴下。默認(rèn)的法線方向是(0,0,1)這和我們需要的正好相反渗稍。

Normals are defined per vertex, so we have to fill another vector array. Alternatively, we can ask the mesh to figure out the normals itself based on its triangles. Let's be lazy this time and do that.

每個頂點定義一個法線竿屹,所以我們必須填充另一個向量數(shù)組拱燃⊥胗或者,我們可以讓網(wǎng)格根據(jù)它的三角形求出法線尝苇。這次讓我們偷懶吧糠溜。

private?void?Generate ()

?{

????…

????mesh.triangles = triangles;mesh.RecalculateNormals();

}

How are normals recalculated?


Without vs. with normals.?有法線和沒法線

Next up are the UV coordinates. You might have noticed that the grid currently has a uniform color, even though it uses a material with an albedo texture. This makes sense, because if we don't provide the UV coordinates ourselves then they're all zero.

接下來是UV坐標(biāo)凯肋。您可能已經(jīng)注意到網(wǎng)格當(dāng)前只有一種顏色圈盔,盡管它使用了具有反照率紋理的材質(zhì)驱敲。這是有道理的众眨,因為如果我們不自己提供UV坐標(biāo)那么它們都是零。

To make the texture to fit our entire grid, simply divide the position of the vertex by the grid dimensions.

要使紋理與我們的整個網(wǎng)格適應(yīng)沿腰,只需將頂點的位置除以網(wǎng)格的維數(shù)。

vertices =?new?Vector3[(xSize +1) * (ySize +1)];

Vector2[] uv =new?Vector2[vertices.Length];

for(inti =0, y =0; y <= ySize; y++)

?{

for(intx =0; x <= xSize; x++, i++)

?{

vertices[i] =newVector3(x, y);

uv[i] =newVector2(x / xSize, y / ySize);

}

}

mesh.vertices = vertices;

mesh.uv = uv;


Incorrect UV coordinates, clamping vs. wrapping texture.

The texture shows up now, but it's not covering the entire grid. Its exact appearance depends on whether the texture's wrap mode is set to clamp or repeat. This happens because we're currently dividing integers by integers, which results in another integer. To get the correct coordinates between zero and one across the entire grid, we have to make sure that we're using floats.

紋理現(xiàn)在出現(xiàn)了措嵌,但是它沒有覆蓋整個網(wǎng)格。它的確切外觀取決于紋理的wrap mode設(shè)置為clamp?還是repeat∪美伲現(xiàn)在這種情況是因為我們正在用整數(shù)除以整數(shù)涕俗,結(jié)果是另一個整數(shù)萌抵。為了在整個網(wǎng)格中得到0和1之間的正確坐標(biāo),我們必須確保使用的是浮點數(shù)霎桅。

uv[i] =newVector2((float)x / xSize,(float)y / ySize);

The texture is now projected onto the entire grid. As I've set the grid's size to ten by five, the texture will appear stretched horizontally. This can be countered by adjusting the texture's tiling settings of the material. By settings it to?(2, 1)?the U coordinates will be doubled. If the texture is set to repeat, then we'll see two square tiles of it.

紋理現(xiàn)在投射到整個網(wǎng)格上。當(dāng)我將網(wǎng)格的大小設(shè)置為10×5時揭糕,紋理將呈現(xiàn)水平拉伸的狀態(tài)著角。這可以通過調(diào)整材質(zhì)的貼圖設(shè)置來解決吏口。通過將它設(shè)為(2,1)U坐標(biāo)會加倍产徊。如果紋理設(shè)置為重復(fù)舟铜,那么我們將看到它的兩個正方形塊深滚。


Correct UV coordinates, tiling 1,1 vs. 2,1.

Another way to add more apparent detail to a surface is to use a normal map. These maps contain normal vectors encoded as colors. Applying them to a surface will result in much more detailed light effects than could be created with vertex normals alone.

另一種為表面添加更明顯細(xì)節(jié)的方法是使用法線貼圖。法線貼圖包含了用顏色編碼的法線生兆。將它們應(yīng)用到一個表面會產(chǎn)生比僅用頂點法線更細(xì)膩的光照效果。


A bumpy surface, made metallic for dramatic effect.

Applying this material to our grid doesn't give us any bumps yet. We need to add tangent vectors to our mesh first.

將這種material?應(yīng)用到我們的網(wǎng)格中還沒有任何高低不平顛簸的感覺 合蔽。我們需要先在網(wǎng)格中加入切線拴事。


How do tangents work?? 切線有什么用?

Normal maps are defined in tangent space. This is a 3D space that flows around the surface of an object. This approach allows us to apply the same normal map in different places and orientations.

法線貼圖是在切空間中定義的刃宵。這是一個圍繞物體表面流動的三維空間哮针。這種方法允許我們在不同的位置和方向上應(yīng)用相同的法線貼圖坦袍。

The surface normal represents upward in this space, but which way is right? That's defined by the tangent. Ideally, the angle between these two vectors is 90°. The cross product of them yields the third direction needed to define 3D space. In reality the angle is often not 90° but the results are still good enough.

表面法線在這個空間中表示向上的方向捂齐,但哪個方向是正確的辛燥? 這是由切線定義的。 理想情況下榴都,這兩個矢量之間的角度為90°嘴高。 它們的叉積產(chǎn)生了定義3D空間所需的第三個方向拴驮。 實際上套啤,角度通常不是90°潜沦,但結(jié)果仍然足夠好。

So a tangent is a 3D vector, but Unity actually uses a 4D vector. Its fourth component is always either ?1 or 1, which is used to control the direction of the third tangent space dimension – either forward or backward. This facilitates mirroring of normal maps, which is often used in 3D models of things with bilateral symmetry, like people. The way Unity's shaders perform this calculation requires us to use ?1.

切線 是一個3D向量争占,但Unity實際上用的是4D向量。其第四個值總是?1或1,用于控制第三切線空間維度的方向,向前或向后(法線和切線叉積可以求出副切線?這個值用于控制它的方向)唆樊。這有助于映射法線貼圖,它通常用于雙邊對稱事物的三維模型中片效,比如人淀衣。Unity著色器執(zhí)行此計算要求使用?1膨桥。

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

因為我們有一個平面只嚣,所有的切線都指向同一個方向册舞,也就是右邊调鲸。


A flat surface pretending to be bumpy.

Now you know how to create a simple mesh and make it look more complex with materials. Meshes need vertex positions and triangles, usually UV coordinates too – up to four sets – and often tangents as well. You can also add vertex colors, although Unity's standard shaders don't use those. You can create your own shaders that do use those colors, but that's something for another tutorial.

現(xiàn)在你知道如何創(chuàng)建一個簡單的網(wǎng)格徐伐,然后用material讓它看起來更加復(fù)雜角雷。網(wǎng)格需要頂點位置和三角形性穿,通常也需要UV坐標(biāo)——最多4個集合——還有切線吗坚。你也可以添加頂點顏色祈远,盡管Unity的標(biāo)準(zhǔn)著色器不使用這些。您可以創(chuàng)建自己的著色器商源,使用這些顏色车份,但這是另一個教程的內(nèi)容。

Once you're satisfied with your grid, you can move on to the?Rounded Cube?tutorial.

如果您對本節(jié)課程感覺還行聽得懂牡彻,就可以繼續(xù)學(xué)習(xí)?Rounded Cube?教程扫沼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市庄吼,隨后出現(xiàn)的幾起案子器罐,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孽文,死亡現(xiàn)場離奇詭異郁副,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人件蚕,你說我怎么就攤上這事下愈÷囊颍” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長粱甫,這世上最難降的妖魔是什么节预? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任会傲,我火速辦了婚禮顾瞻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般从铲。 火紅的嫁衣襯著肌膚如雪伸辟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天杀迹,我揣著相機(jī)與錄音,去河邊找鬼。 笑死苛白,一個胖子當(dāng)著我的面吹牛躯畴,可吹牛的內(nèi)容都是我干的嚷缭。 我是一名探鬼主播劝赔,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼予借,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了舟肉?” 一聲冷哼從身側(cè)響起脏款,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤万俗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后饱亿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚂且,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡系忙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年捺弦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片香浩。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡驮瞧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出待错,到底是詐尸還是另有隱情沟启,我是刑警寧澤称杨,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布袭蝗,位于F島的核電站,受9級特大地震影響栈拖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜童番,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一糟秘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧躲舌,春花似錦、人聲如沸贪庙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽收叶。三九已至俏竞,卻和暖如春酣胀,著一層夾襖步出監(jiān)牢的瞬間猴凹,已是汗流浹背购对。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工徘溢, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搔弄。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像灰伟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疗韵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,347評論 0 10
  • 夜色讓我們變得虛偽甚至比動物更虛偽黑暗保護(hù)著那些擁有遲鈍觸覺的人春天是最后一批攻占他們的特種兵日影爬過青磚翠瓦的院...
    臨冬雪狼閱讀 204評論 0 0
  • 早戀的殺手少女 程諾硬塞給王南的幾個水果仗岸,一直在他手里緊緊握著,疑似撞鬼的時候沒有松手,女孩張口閉口殺人的時候沒有...
    諾陽閣閱讀 284評論 0 1
  • 在你目前為止的人生中忍宋,哪些事情是持續(xù)做的最久的宽菜? 初看這句話,是在提問什么事情是持續(xù)時間最長的竿报?然而再往深處想铅乡,就...
    h先貹閱讀 219評論 0 2