XNA是使用DirectX 9的Rendering pipeline來繪製圖形,而下圖就是一個簡單的概觀:
接下來就針對這些區塊的來做簡介。
Vertex Data(頂點資料):
Vertex Data他是一個Buffer,用來儲存頂點的資訊,包含像是頂點的座標(position)、頂點的法相量(normal)、頂點顏色(color)和貼圖座標(texture coordinate)等。在XNA中你可以用VertexDeclaration來描述上述的資訊,而這些頂點的資料將會被放到VertexBuffer中。
Primitive Data:
這邊主要提供的概念就是Index Buffer,而Index buffer就是用來決定幾何圖形的連接順序。
在3D世界中,所有的模型都是幾何資料組成,像是點(point)、線(line)、三角形(triangle)等等,而Index buffer儲存的就是頂點位置,然後在pipeline中,會依據index buffer的順序,將頂點給組合起來,像是點、線、三角形或是多邊形等。
而當然使用者可以不指定Index Buffer,然後他就會用預設的方式去做連結,而這個結果可能是你無法預期的,所以我們通常將頂點設定完畢以後,會在設定Index Buffer設定連結順序。
EX:
Vertex Buffer:
1 2 3 4…
a b c d…(這些就包含座標、法向量、貼圖座標等)
Index Buffer:
1 2 3 4 5 6
1 2 3 1 3 2
就可以得到以下圖形的連接方式:
這邊我只是概略的簡介想法,當中這邊涉及很多內容,像是甚麼是front face,還有就是使用的座標系等等。
Front face:
在3D空間中,我們可以由三個點可以組成一個平面,而每個平面都會有法向量(normal),而所謂的Front face就是指,法向量方向跟眼睛觀察的方向的內積結果為負值,則該平面就是Front face。如下圖:
在3D座標系的部分分為兩種,左手座標系跟右手座標系兩種。(DirectX使用左手座標系)
Vertex Processing:
這個階段會接收Vertex data和Primitive data的資訊內容。在這個階段,這邊會包含一個Shader(著色器) – Vertex shader,這是一個可程式化的操作,而XNA跟DirectX使用的Shader語言是HLSL(High level shader language)。
在傳統的Rendering pipeline中,我們只能接收頂點,然後再將它畫到畫面來,無法針對頂點去做操作,像是改變顏色之類的,這些操作根本不可能做到。而有了Vertex Shader以後,現在我可以對Normal或是頂點顏色,去做些計算改變。打破了以往很多都要先在CPU計算完畢以後再送入Pipeline的情況。
同時,這邊還會去做一個計算,也就是將Local的點,轉換至World coordinate上。(因為每個模型都會有一個Local coordinate的點座標,所以我們需要經由一個轉換,轉換至World coordinate上,而所有的3D物件,都會在相同的世界座標系上面)。這個轉換就包含了View matrix和projection matrix等。
View matrix做的事情主要就是將,Camera的位置移動到原點上面,讓Camera成為座標系的原點,而當然全部場景也會跟著一起轉換,如下圖:
進行這種轉換的好處:
- 在後面做projection的時候比較方便。
- 方便做Clip的動作,clip指的就是將View frustum之外的物件移除掉。如下圖:
Projection matrix就是將View Frustum normalize,也就是將它的範圍變到[-1, 1],稱為unit cube或是canonical。如下圖:
所以,在Vertex processing中,我們可以去對頂點去做處理。
Geometry Processing
這邊做的事情包含上面所說的Clip、back face culling和rasterization等。
Clip: 將在View Frustum之外的polygon給切掉。因為那些部分不會被畫出來,所以我們先把它移除掉。之後的所有處理都不會在計算他們。
Back face culling: 上面有解釋過甚麼是front face,而這邊做的事情就是將Back face的部分剔除掉。
上面兩個操作,都是為了降低計算量,因為這些多邊形使用者並不能看到,所以我們先將它處理掉,這樣後面就不用再去計算它。
Rasterization: 到目前為止我們現在接收到的是primitive,也就是只有頂點和邊的連接。以三角形當作連接方式來說,rasterization接收的資料就是三角形(三個頂點),而我們要把它畫到螢幕上的話,就會有一個問題產生,螢幕上是pixel,我們將三角形切成一個一個的pixel,並且內插它的座標、貼圖座標和法向量等。然後在將這些pixel(fragment)送往下一個階段進行計算。
Texture sampler:
這邊的操作會由pixel processing中的Shader來存取貼圖。
Pixel processing:
包含一個shader – pixel shader,針對現在接收進來的Pixel去做一些計算,像是貼圖和打光等等。
Pixel rendering:
這個階段有些Test的機制,使用者可以用這些Test來做些操作。
- Alpha test: 進行Alpha的透明度測試,可能會需要用到混色的效果。
- Depth test: 進行深度上的測試,因為在現在的volumn中,包含了很多的pixel,而我們在乎的就是最前面的部分,因為這個部分是使用者可以看到的,所以經由這個test我們可以獲得到使用者可以看到的深度值。如下圖:
- Stencil test: 模板測試,指定現在這個畫面中甚麼Pixel可以畫到螢幕上面。
這三個Test的操作流程為
- 先檢查看看現在這個畫面中的Pixel是不是通過Stencil test
- 如果通過以後,在檢察alpha test,這邊做這個檢查的好處是,因為透明的物件也是會有深度的影響,所以我要先檢查這個部分,在做深度測試,先排除掉透明的物件,以免影響到深度的測試。
- 深度檢察,計算遮擋效應。
完成這些操作以後,就會將畫面畫到螢幕中的畫面。
上述的pipeline是XNA使用DirectX 9.0的Pipeline,而下張圖片是貼出目前最新的DirectX 11 Pipeline:
先簡介Geometry shader,在這邊使用者可以新增頂點或是刪除頂點等的操作,這些操作在以前9.0的pipeline是無法做到的,而有了geometry shader,現在我們可以對一個粗糙的模型,去做細緻的動作(讓模型看起來更細緻,這邊有一個詞叫做tessellation)。
上面的geometry shader是在DirectX 10中所提出。
而11新增兩個Shader - Hull shader和Domain shader,用來增強tessellation的部分。
最後就是跟大家說一下,XNA在360上面的限制。
XNA的遊戲專案如果你要部屬到360上面,你不可以用到P-Invoke的pointer。
而甚麼是P-Invoke,也就是所謂的platform invoke,是用unmanage code來撰寫的dll檔案。
而用.net framework寫的DLL檔案就是manage code,而要傳送到360上面的話,需要是用manage code才行。
這個限制僅限於360,PC上面是沒有關係的。
檔案下載: http://140.126.21.8/~teexit/xna/pic/Rendering/render%20pipeline.pdf
留言列表