Vertex Transformation(頂點變換)

  在前面的章節裏面我們已經知道定義一個model需要頂點buffer,索引buffer和primitives,也知道可以使用多路流來實現動態頂點components.如果我們想要移動一個model,我們可以通過鎖住頂點buffer,然後編輯它某些組件來達到這樣的效果。Direct3D提供了頂點處理流水線來執行這樣的轉換,它包括平移,旋轉和縮放。

  頂點處理是指發生在被渲染的每個primitive的每個頂點上的所有計算。頂點處理的每一個stage都會對它的一個或者多個components產生作用。Direct3D允許應用程序選擇頂點的處理方式(硬件處理,軟件處理或者兩者結合)。也可以只是對頂點進行處理,而不進行渲染。

   頂點的變換矩陣一般是一個4*4的浮點矩陣。這個矩陣一般只執行平移,旋轉或者縮放。

   當使用多個轉換矩陣的時候,變換矩陣的順序一般也會改變產生的結果,這是因爲矩陣乘法不支持交換律。

   世界變換是頂點處理的第一步,它可以把模型空間的頂點轉換到世界空間。轉換矩陣可以通過方法GetTransform,SetTransform和MultiplyTransform來操作。

   也可以用矩陣變換來實現場景的層次結構。場景的層次結構可以用於繪製那些被連接起來的人物結構或者有相對定位的模型,例如一個機器人的手臂。

   一個頂點可以使用多個世界變換,這些變換結果通過加權結合在一起產生想要的結果,這樣的變換方式叫做頂點blending. Direct3D提供了很多blending操作選項設置。最簡單的頂點transform是Tweening,就是使用一個浮點值作爲通過兩個世界變換矩陣變換後頂點的權重值。頂點的權重值在頂點components裏面被給出。

    通常的頂點blending一般會提供2到3個權重值以及相應的3個或者4個變換矩陣。被索引的頂點blending可以允許多大4個不同矩陣用於變換。對於未被索引頂點的blending,一個primitive的所有的頂點變換矩陣必須是一樣的,只是他們的權重值可以不一樣。對於索引頂點blending,每個頂點的索引可以變化,這樣頂點的變換矩陣可以不一樣。

    在這一章裏面,我們將講述霧化,面揀選,用戶自定義剪裁面,視截體,同次除法和view port的應用。

 

頂點處理

   在以前的章節裏面,設備支持軟件,硬件以及軟硬結合的頂點處理方式。當設備使用軟硬結合的處理方式的時候,GetSoftwareVertexProcessing和SetSoftwareVertexProcessing用來控制是軟件處理還是硬件處理。當這個render state爲true時,就意味着軟處理被選擇,否則則硬處理被選擇。當這個render state改變時,當前流,當前索引以及當前頂點shader需要重新還原到默認值。頂點處理包括:世界變換,紋理座標產生,紋理變換,視覺變換(View Transform),頂點霧化,面揀選,用戶剪裁面處理,視截體剪裁,同次除法和視口映射。頂點處理的結果被稱爲“transformed and lit”頂點,它攜帶一個屏幕空間的位置,diffuse和specular顏色,最多8組紋理座標。這些信息都是需要傳遞給光柵器。如果頂點位置格式是D3DFVF_XYZRHW,就會忽略所有的頂點處理,直接傳遞給光柵器。

 

變換矩陣

   在數學上,座標變換是從一個座標系映射到另外一個座標系。在三維座標系,我們需要能夠旋轉,縮放,平移一個物體。我們可以列出一個跟一維類似的方程:

P'  =  PM +  b  = [x , y z ] M + [b1 b2 b3]

   這裏M是一個3*3的矩陣, 它實現了旋轉和縮放,而b實現了平移。但是如果使用同次座標,我們則只需要一個矩陣就能實現這三個功能。當P的笛卡爾座標擴展到同次座標時,4*4的矩陣可以同時對三維的點做平移,旋轉和縮放。P'= PM',M'是由M和b組成的,如:[x',y',z',1]= [x,y,z,1]M'。這個同次轉換矩陣也可以利用它最右邊的一欄用於透視圖的距離縮短處理。

   當一個頂點包含一個面法線時,面法線將和頂點在同一座標系。當頂點被轉換到新的座標系是,面法線也應該要轉換。但是法線不應該被扭曲。所以,如果頂點用M做轉換,面法線的變換矩陣應該是M的逆矩陣的轉置。

 

世界變換

   在第五章裏面我們已經知道怎麼在模型空間建模。世界變換是頂點處理的第一步,將模型從模型空間轉換到世界空間。

   如果頂點組件裏面也包含面法線,則面法線也需要被轉換。不過位置組件是一個點,但是法線是一個向量。爲了保持表面法線的方向,Direct3D使用一個新矩陣來轉換它。這個新的矩陣就是頂點變換矩陣的逆矩陣的轉置。不過這個矩陣仍然包含縮放,可以改變法向量的長度。

  RS Vertex Blend 可以用來控制世界變換的類型,它的值定義在D3DVERTEXBLENDFLAGS裏面。當RS Vertex Blend爲D3DVBF_DISABLE時,頂點將只有一個變換矩陣。

typedef enum _D3DVERTEXBLENDFLAGS

{

     D3DVBF_DISABLE = 0,

     D3DVBF_0WEIGHTS = 256,

     D3DVBF_1WEIGHT = 1,

     D3DVBF_2WEIGHT = 2,

     D3DVBF_3WEIGHT= 3,

   D3DVBF_TWEENING = 255

}

   GetTransform和SetTransform方法管理設備的變換矩陣的屬性。D3DTRANFORMSTATETYPE給出了不同類型變換的類型,當vertex blending 被disable的時候使用D3DTS_WORLD。

typedef enum _D3DTRANSFORMSTATETYPE

{

     D3DTS_WORLD= 256,

     D3DTS_WORLD1 = 257,

     D3DTS_WORLD2 = 258,

     D3DTS_WORLD3 = 259,

     D3DTS_VIEW   = 2,

     D3DTS_PROJECTION= 3,

   D3DTS_TEXTURE0 = 16,

     D3DTS_TEXTURE1 = 17,

     D3DTS_TEXTURE2 = 18,

     D3DTS_TEXTURE3 = 19,

     D3DTS_TEXTURE4 = 20,

     D3DTS_TEXTURE5  = 21,

     D3DTS_TEXTURE   = 22,

     D3DTS_TEXTURE   = 23

} D3DTRANSFORMSTATETYPE;

 

 

變換層次

   除了使用SetTransform來設置設備的變換屬性外,你也可以在現有的矩陣上乘以一個新矩陣。如果一個模型由很多個相互關聯的部分組成,MultiplyTransform可以用於每個部門的相對轉換。

 

頂點Blending

  連接起來的linkage對於處理那些生硬的機器人還可以,但是其他物體如布,植物或者動物,這些都需要靈活的而需要精確描述的動作,用層次變化就行了。模擬動物行走的一種方法是把一個模型變換多次,每次都使用不同的矩陣,然後使用一組權重值把把這些結果組合起來產生一個最終的輸出。最簡單的例子,就是隻使用一個權重值,兩個變換矩陣,方程式:P' = bP1 + (1-b)P2= bPM1 + (1-b)PM2。

  這個權重值b,定義了每個頂點的轉換比率,它通常是被一些3D建模工具。

  • 基本頂點blending

  Direct3D 通過RS Vertex Blend的D3DVERTEXBLENDFLAGS來設定固定功能處理。當這個值是D3DVBF_1WEIGHTS, D3DVBF_2WEIGHTS, D3DVBF_3WEIGHTS分別表示每個頂點有1,2,3個權重值。如果指定D3DVBF_0WEIGHTS,那只有一個矩陣,它跟D3DVBF_DISABLE一樣。D3DCAPS9::MaxVertexBlenMatices指定可以使用的最多變換矩陣的數目。當使用FVF定義頂點的格式時,D3DFVF_XYZBn 只是在位置組件裏面存放了權重的數目。D3DFVF_XYZB1,D3DFVF_XYZB2,D3DFVF_XYZB3最後一個權重值是隱式的被計算,而D3DFVF_XYZB4則直接給出b0,b1,b2,b3,不需要額外計算最後一個權重值。D3DFVF_XYZB5給出了b0,b1,b2,b3,b4則是blend被索引頂點blending的矩陣索引。

  當使用定點shader聲明來定義頂點時,權重值需要映射到blend weights usage. blend 矩陣索引映射到blend weights matrix indices. 權重b1,b2,b3,b4分別對應D3DTS_WORLD, D3DTS_WORLD1,D3DTS_WORLD2,D3DTS_WORLD3. 在Direct3D裏面,每個定點blend矩陣通常包含變形矩陣和世界矩陣。當變形矩陣在世界空間中時,或者當在模型變形後在使用世界變換,兩個矩陣可以很容易被組合起來。前者使用WD,後者使用DW.

  • 被索引的頂點blending

   使用定點blending,能夠實現很多模型的變形。但是在某種程度上它對於很多複雜的有很多連接點的模型來說,也很難描述的很好,例如人。並且頂點blending最多也只有四種變形,並且在每個DrawPrimitive的調用過程中這幾種變形必須被所有的頂點使用。

   使用被索引頂點blending ,也稱作矩陣palette蒙皮,矩的索引被保存在每個頂點,它可以從palette選擇一個矩陣使用。攜帶N個權重值的將使用N+1個矩陣和N+1個矩陣索引。這允許每個頂點最多四個矩陣,每個三角形最多12個矩陣。被索引的頂點blending是通過RS Indexed Vertex Blend Enable控制,而頂點blending則是通過D3DRS_VERTEXBLEND. 矩陣palette的最多數目則是通過D3DCAPS9::MaxVertexBlendMatrixIndex.每個頂點支持的最大矩陣數與頂點blending一樣。對於FVF頂點buffer,增加一個額外的“權重”和包含D3DFVF_LASTBYTE_UBYTE來指定矩陣索引值。D3DFVF_LASTBYTE_UBYTE指頂點的最後一個權重值爲矩陣的索引。這個權重值的每個字節代表一個0到255的索引值。如果使用固定功能的頂點shader,矩陣索引流就被映射到它對應的blend indices usage. 如果可編程的shader,這些值可以用於任何寄存器。在這種情況,矩陣索引被聲明稱D3DDECLTYPE_D3DCOLOR,他們將被縮小到【0,1】範圍,如果矩陣索引被聲明爲D3DDECLTYPE_SHORT2或者D3DECLTYPE_SHORT4,則不進行縮放。

  • 頂點Tweening

   一些頂點blending效果並不能通過矩陣的頂點混合取得,但可以通過Tweening 方法實現。Tweening 這個名字是來源於電影動畫,使用一個animator,繪製起始和結束姿勢繪製角色,另外一個animator繪製中間的frame。固定功能的流水線提供了一種類似電影的頂點tweening。當D3DCAPS::VertexProcessingCaps 的D3DVTXPCAPS_TWEENING被設置,則設備就支持Tweening。

   每個頂點定義兩個位置(P1, P2),兩個法線是可選。在進行世界矩陣之前,P1和P2通過Tweening參數f結合起來。

   P' = ((1-f)P1 + fP2)M

  當RS Vertex Blend爲D3DVBF_TWEENING,Tweening被激活。固定功能的頂點Tweening必須使用頂點shader聲明。Tweening也需要上次出現在頂點裏面的第二個位置組件和法線。頂點聲明把P1和P2映射到頂點位置usage,usage索引是0和1.使用頂點Tweening,每個頂點的處理都是獨立的,互不關聯。但是Tweening不能引入和刪除頂點。

 

頂點霧化

   霧化也稱作depth-cueuing,它是根據物體距離照相機的距離來改變物體顏色的一種效果,通過霧化參數將物的顏色混合到頂點的顏色裏面。

   C' = fC + (1-f)C

   f是根據物體距離照相機的距離計算出來的。霧化只是改變物體的顏色,但是它不會改變物體的透明度。因此,Alpha在霧化的過程不會改變。

   Direct3D 提供了兩種霧化應用,頂點霧化和像素霧化。一次只能使用他們其中的一種,可編程的頂點shader只支持頂點霧化。使用頂點霧化,頂點處理的時候會計算出每個霧化係數,並且這些霧化係數也會被光柵器插值來計算每個像素的霧化係數。使用像素霧化,也稱作table fog,光柵器計算出每個像素的霧化係數,根據距其depth來查詢一張霧化係數表。Direct3D也允許應用程序計算霧化係數。一旦霧化係數被計算出來,霧化blend過程將會在像素處理的最後一個階段進行。

   RS Fog Enable控制是否開啓霧化處理。霧的顏色通過RS Fog Color指定,只有RGB channel。  RS Fog Vertex mode和RS Fog Table Mode從D3DFOGMODE中取值,並且分別選擇頂點和像素霧化。如果D3DCAPS9::RasterCaps的D3DPRASTERCAPS_FOGVERTEX或者D3DPRASTERCAPS_FOGTABLE被設定,則設備支持頂點霧化或者像素霧化。如果D3DCAPS9::LineCaps的D3DLINECAPS_FOG被設置,則霧化只支持點和線primitive.

typedef enum _D3DFOGMOD

{

   D3DFOG_NONE= 0,

  D3DFOG_LINEAR  = 3,

   D3DFOG_EXP = 1,

   D3DFOG_EXP2 = 2

} D3DFOGMODE;

   當深度值在Zs(RS Fog start),Ze(RS Fog end)範圍內,線性霧化是一個物體本來顏色到霧顏色線性轉化的過程。Exponential 霧化提供能更加平滑的轉化。Exponential有一個霧density係數。

   計算霧化距離是計算照相機離深度z的平面的距離,這種點到image中心的距離,其實不是真正的照相機到點的距離。Range-based的霧計算出點到照相機的真實距離。如果D3DCAPS9::RasterCaps的D3DPRASTERCAPS_FOGRANGE,設備支持基於range-based的霧。RS Range Fog Enable控制Range-based的霧化過程。

   使用在霧化計算過程的深度值的座標空間可能變化。在頂點霧化過程中,霧化距離是在camera空間計算的。深度值的範圍[Zn,Zf]他們是近平面和遠平面的的位置。在像素霧化過程中,霧化距離是是使用Z buffering在【0,1】範圍內,或者在camera空間使用w buffering。如果D3DCAPS9::RasterCaps的D3DPRASTERCAPS_ZFOG或者D3DPRASTERCAPS_WFOG被設置,設備將分別支持z buffer 霧化和w buffer霧化。

   使用固定功能頂點處理,霧化係數存儲在specular component的Alpha channel。使用可編程頂點處理,霧化係數可以存儲在數據流的任意位置,或者在shader裏面通過其他數據計算出來。

 

Face Culling

   大部分模型都只有大約一般的三角形是可視的。當三角形已經轉化到了camera空間,如果三角形可見,它的法向量是指向camera的,則那些背離camera朝向的三角形,它就不可見。我們可以使用這種方法做face culling. 這樣就避免不可見的三角形做光柵處理。

   Face culling 使用三角形的面法線。但是Direct3D並不會使用頂點組件的法線來用來做Face culling. Face culling是三角形的屬性,並不是三角形模擬的光滑表面的屬性。法線是通過三角形的頂點計算的,任何面法線向量都是面裏面兩個向量的叉集。

   RS Cull mode指定Face culling的模式,它包括D3DCULL_NONE, D3DCULL_CW和D3DCULL_CCW.  D3DCULL_NONE禁止了face culling. D3DCULL_CW cull 那些被轉換後的頂點以順時針出現的三角形,D3DCLL_CCW 則是cull 被轉換後的頂點以逆時針出現的三角形。

   D3DCAPS9的PrimitiveMiscCaps的三個bit來指定設備的支持能力。

 

Clipping

   當primitive在某個邊界之外,則這個頂點就會被刪除。這個邊界可能是render target的邊界,也可能是3維空間的任意的面。當一個primitive被刪除的時候,邊界以內的部分就確定了,就可以渲染這個部分了。剪裁面和模型的相交,可以產生新的頂點。新的頂點就是剪裁面和物體模型幾何體相交的點。當線和三角形被剪裁掉,新的頂點產生。面的法線,紋理座標,diffuse , specular可以通過插值取得。

   Direct3D 提供了集中面剪裁的方式,一種是用戶自定義的面,一種是通過視截頭體。視截頭體提供的是一個照相機顯示的空間。Guard band剪裁則類時與視截體空間剪裁,但是它在某些設備能提供更好的性能優化。還有一些frame buffer的操作,如Z test, alpha test, stencil test和一些像素shader,也可以被認爲是剪裁操作。但是,這些操作的對象是像素,而不是集合體。

  • 用戶clip 面

  用戶自定義的clip面最多提供6個面,每個面有一個組係數定義。它可以用於固定功能流水線和可編程頂點處理。clip面的序號是0到5。 可以通過GetClipPlane和SetClipPlane. RS Clip plane enable 控制是否使用這個clipping.

  • 視截體clipping

  如果RS Clipping爲真,則視截體clipping被使用。當視截體clipping或者用戶定義面被clipping,設備返回clip狀態的被剪裁的primitives的信息。當primitive被處理,並且它與剪裁面相交,它將會在clip狀態裏面設置一個位。如果一個primitive 完全在視截體的外面,它將被culled. Clip status使用GetClipStatus和SetClipStatus管理。這個狀態本身是保存在D3DCLIPSTATUS9裏面的。

typedef struct _D3DCLIPSTATUS9

{

   DWORD ClipUnion;

   DWORD ClipIntersection;

} D3DCLIPSTATUS9

  • Guard Band clipping

  它類似與視截體clipping,它是基於像素操作,不是基於模型集合。Guard band是一個覆蓋當前視口的區域。任何在當前視口以外但是guard band以內的primitive都會被刪除。

  如果能保證所有的幾何體都在guard band內部,昂貴的幾何clipping和插值將會被忽略,如果不能保證,視截體clipping必須要使用。Guard band 的範圍 GuardBandLeft, GuardBandRight, GuardBandBotttom,GuardBandTop,它們的值都在屏幕空間。

 

 Screen Space and ViewPort

    齊次除法和視口應用位於頂點和除法之間。在world ,view , projection轉換後,頂點已經位於標準視圖空間的齊次點(x,y,z,w)。在這個空間把所有的點除以w將會得到一個笛卡爾座標系的標準空間。

    對於已經處於正交的笛卡爾座標系統裏面的頂點,他們已經準備映射到screen空間了。這種映射是被viewport定義的。它能把場景只渲染在render target的一個子區域,或者深度buffer一段小區域,或者兩則結合。視口是屏幕空間的一個矩形,他的深度區間範圍是在【0,1】。默認的視口占據整個render target區域,整個深度區域。

viewport 映射可以用下面的方程式表示:

M = S(w/2, h/2,Zf - Zn) T(Xs,Ys,Zn)

這個轉換把x 從【0,1】映射到[Xs,Xs+w],y 從【0,1】映射到【Ys,Ys+h】,z 從【0,1】到[Zn, Zf]。只有位置組件受它的影響。

typedef struct _D3DVIEWPORT9

{

   DWORD X;// XY是左上的座標

   DWORD Y;

   DOWRD Width;

   DWORD Height;

   float MinZ;

   float MaxZ;
}D3DVIEWPORT9;

Z的範圍是讓應用程序使用depth buffer執行一些可視效果檢測。

一旦視口處理結束,頂點處理就結束了。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章