在骨骼動畫網(wǎng)格模型中,骨骼的變動導(dǎo)致軀體網(wǎng)格模型的改變,于是就有了骨骼動畫。網(wǎng)格模型是由一個個頂點構(gòu)成的,如果任意一個頂點只受一塊骨骼影響,那么網(wǎng)格模型在運動時很容易出現(xiàn)裂縫,特別是在一些結(jié)合部位,如肩關(guān)節(jié)、肘關(guān)節(jié)等。盡管可以使用縫合技術(shù)縮小這些裂痕,但當(dāng)關(guān)節(jié)的旋轉(zhuǎn)比較極端時,例如前臂繞肘關(guān)節(jié)旋轉(zhuǎn)120度時,就會在肘關(guān)節(jié)處出現(xiàn)一個較大的剪缺。這是因為只有一個多邊形跨越在上臂和前臂之間的整個間隙,間隙越大,裂縫就越大,最終的渲染效果也越差。
采用蒙皮骨骼動畫網(wǎng)格模型則可以很好地解決這一問題,蒙皮骨骼動畫網(wǎng)格模型假定其中的一個頂點可以受多塊骨骼影響,網(wǎng)格中的每個頂點包含一個影響它的骨骼列表。骨骼列表提供了影響該頂點的每個骨骼的權(quán)重信息,這些權(quán)重信息表示具體的每塊骨骼將對該頂點產(chǎn)生多大的影響,任何一個頂點的所有骨骼權(quán)重之和是1.0。對于蒙皮網(wǎng)格模型,Direct3D首先會根據(jù)骨骼權(quán)重和骨骼矩陣對頂點數(shù)據(jù)(包括頂點位置和頂點法向量)進行混合,然后進行渲染。
這項技術(shù)稱為圖形混合(或稱為頂點混合)。假設(shè)某個頂點平均地附屬到兩塊骨骼上,這意味著兩塊骨骼對于該頂點的權(quán)重分量都是0.5,即該頂點將從每塊骨骼上各繼承50%的運動,所以這項技術(shù)也稱為"骨骼蒙皮調(diào)色",權(quán)重一般是根據(jù)頂點所附屬的份數(shù)和從頂點到每塊骨骼的距離進行劃分的,不過這些工作在大多數(shù)三維建模軟件中已經(jīng)事先計算好了,程序員需要做的工作只是加載保存在網(wǎng)格模型中的蒙皮信息,即骨骼矩陣和相應(yīng)的權(quán)重,并將其應(yīng)用到網(wǎng)格模型各部分的變換以及最終的渲染。
圖形混合
Direct3D提供了圖形混合技術(shù),即蒙皮技術(shù),實現(xiàn)了具有平滑關(guān)節(jié)的效果,特別是角色模型的渲染,從而提高了場景的真實感。
下圖演示了圖形混合的基本原理,它對最初的圖形進行了兩次變換,第一次沒有對頂點進行變換,相當(dāng)于對頂點數(shù)據(jù)乘以一個單位矩陣,第二次對圖形進行了簡單的旋轉(zhuǎn)變換,相當(dāng)于對頂點數(shù)據(jù)乘以一個旋轉(zhuǎn)矩陣,將兩次變換后的頂點數(shù)據(jù)進行混合,然后渲染就得到了最終顯示的圖形。
通常調(diào)用IDirect3DDevice9::SetTransform()函數(shù)設(shè)置世界變換矩陣時將第一個參數(shù)設(shè)置為D3DTS_WORLD,但要實現(xiàn)上圖所示的圖形混合效果,需要使用兩個世界坐標(biāo)變換矩陣,這時需要將第一個參數(shù)設(shè)置為D3DTS_WORLDMATRIX宏,第二個參數(shù)設(shè)置為相應(yīng)的混合變換矩陣。
在對頂點位置和法線進行混合時,每個混合矩陣對最終的頂點位置和法線的影響大小由混合權(quán)重來決定。混合權(quán)重是0.0 ~
1.0之間的浮點數(shù),0.0表示該權(quán)重對應(yīng)的混合矩陣對頂點位置和法線向量沒有影響,1.0表示頂點的位置和法線完全通過該權(quán)重對應(yīng)的混合矩陣進行變換,權(quán)重也是頂點數(shù)據(jù)的一部分。
Direct3D根據(jù)混合矩陣和相應(yīng)的權(quán)重對頂點位置和法線進行現(xiàn)行插值,公式如下:
Vblend = V * (M0
* W0 + M1 * W1 + ... + Mn * Wn)
其中,Vblend表示混合后的頂點,V表示混合前的頂點,M0、M1、...,Mn表示混合矩陣,W0、W1、...,Wn表示混合權(quán)重。
因為所有混合權(quán)重之和為1.0,所以在頂點數(shù)據(jù)中只需保存前n-1個混合權(quán)重,第n個混合權(quán)重為1.0減去前n-1個混合權(quán)重之和。在Direct3D引擎中,影響每個頂點的混合矩陣最大數(shù)量限定為4,所以在Direct3D中頂點混合就有三種情況:
Vblend = V * (M0
* W0 + M1 * (1 - W0))
Vblend = V * (M0
* W0 + M1 * W1 + M2 * (1 - (W0
+ W1)))
Vblend = V * (M0
* W0 + M1 * W1 + M2 * W2
+ M3 * (1 - (W0 + W1 + W2)))
如果使用圖形混合,則在頂點數(shù)據(jù)中必須包含相應(yīng)的混合權(quán)重數(shù)據(jù),盡管在靈活頂點格式中使用D3DFVF_XYZB1 ~
D3DFVF_XYZB5指定頂點數(shù)據(jù)中最多可以包含5個混合權(quán)重,但目前的Direct3D版本最多只使用前面三個混合權(quán)重。在具體渲染圖形時,Direct3D使用幾個混合矩陣和相應(yīng)的混合權(quán)重對頂點進行混合,由渲染狀態(tài)D3DVERTEXBLEND控制,該渲染狀態(tài)的取值為枚舉類型D3DVERTEXBLENDFLAGS。
-
D3DRS_VERTEXBLEND
-
Number of matrices to use to perform geometry
blending, if any. Valid values are members of the D3DVERTEXBLENDFLAGS
enumerated type. The default value is D3DVBF_DISABLE.
D3DVERTEXBLENDFLAGS
Defines flags used to control the number or matrices
that the system applies when performing multimatrix vertex blending.
typedef enum D3DVERTEXBLENDFLAGS
{
D3DVBF_DISABLE = 0,
D3DVBF_1WEIGHTS = 1,
D3DVBF_2WEIGHTS = 2,
D3DVBF_3WEIGHTS = 3,
D3DVBF_TWEENING = 255,
D3DVBF_0WEIGHTS = 256,
} D3DVERTEXBLENDFLAGS, *LPD3DVERTEXBLENDFLAGS;
Constants
-
D3DVBF_DISABLE
-
Disable vertex blending; apply only the world
matrix set by the D3DTS_WORLDMATRIX macro, where the index value for the
transformation state is 0.
-
D3DVBF_1WEIGHTS
-
Enable vertex blending between the two matrices
set by the D3DTS_WORLDMATRIX macro, where the index value for the
transformation states are 0 and 1.
-
D3DVBF_2WEIGHTS
-
Enable vertex blending between the three matrices
set by the D3DTS_WORLDMATRIX macro, where the index value for the
transformation states are 0, 1, and 2.
-
D3DVBF_3WEIGHTS
-
Enable vertex blending between the four matrices
set by the D3DTS_WORLDMATRIX macro, where the index value for the
transformation states are 0, 1, 2, and 3.
-
D3DVBF_TWEENING
-
Vertex blending is done by using the value
assigned to D3DRS_TWEENFACTOR.
-
D3DVBF_0WEIGHTS
-
Use a single matrix with a weight of 1.0.
Remarks
Members of this type are used with the
D3DRS_VERTEXBLEND render state.
Geometry blending (multimatrix vertex blending)
requires that your application use a vertex format that has blending (beta)
weights for each vertex.
在默認情況下,頂點混合是禁用的。要啟用圖形混合功能,只需調(diào)用IDirect3DDevice9::SetRenderState()函數(shù),將渲染狀態(tài)D3DVERTEXBLEND設(shè)置為D3DVERTEXBLENDFLAGS枚舉值中除D3DVBF_DISABLE外的其他值。如果啟用了圖形混合功能,Direct3D就認為在頂點數(shù)據(jù)中包含了合適數(shù)量的混合權(quán)重,程序員的工作就是為圖形渲染提供包含所需數(shù)量混合權(quán)重的頂點數(shù)據(jù)和相應(yīng)的頂點格式。