在骨骼动画网格模型中,骨骼的变动导致躯体网格模型的改变,于是就有了骨骼动画。网格模型是由一个个顶点构成的,如果任意一个顶点只受一块骨骼影响,那么网格模型在运动时很容易出现裂缝,特别是在一些结合部位,如肩关节、肘关节等。尽管可以使用缝合技术缩小这些裂痕,但当关节的旋转比较极端时,例如前臂绕肘关节旋转120度时,就会在肘关节处出现一个较大的剪缺。这是因为只有一个多边形跨越在上臂和前臂之间的整个间隙,间隙越大,裂缝就越大,最终的渲染效果也越差。
采用蒙皮骨骼动画网格模型则可以很好地解决这一问题,蒙皮骨骼动画网格模型假定其中的一个顶点可以受多块骨骼影响,网格中的每个顶点包含一个影响它的骨骼列表。骨骼列表提供了影响该顶点的每个骨骼的权重信息,这些权重信息表示具体的每块骨骼将对该顶点产生多大的影响,任何一个顶点的所有骨骼权重之和是1.0。对于蒙皮网格模型,Direct3D首先会根据骨骼权重和骨骼矩阵对顶点数据(包括顶点位置和顶点法向量)进行混合,然后进行渲染。
这项技术称为图形混合(或称为顶点混合)。假设某个顶点平均地附属到两块骨骼上,这意味着两块骨骼对于该顶点的权重分量都是0.5,即该顶点将从每块骨骼上各继承50%的运动,所以这项技术也称为"骨骼蒙皮调色",权重一般是根据顶点所附属的份数和从顶点到每块骨骼的距离进行划分的,不过这些工作在大多数三维建模软件中已经事先计算好了,程序员需要做的工作只是加载保存在网格模型中的蒙皮信息,即骨骼矩阵和相应的权重,并将其应用到网格模型各部分的变换以及最终的渲染。
图形混合
Direct3D提供了图形混合技术,即蒙皮技术,实现了具有平滑关节的效果,特别是角色模型的渲染,从而提高了场景的真实感。
下图演示了图形混合的基本原理,它对最初的图形进行了两次变换,第一次没有对顶点进行变换,相当于对顶点数据乘以一个单位矩阵,第二次对图形进行了简单的旋转变换,相当于对顶点数据乘以一个旋转矩阵,将两次变换后的顶点数据进行混合,然后渲染就得到了最终显示的图形。
通常调用IDirect3DDevice9::SetTransform()函数设置世界变换矩阵时将第一个参数设置为D3DTS_WORLD,但要实现上图所示的图形混合效果,需要使用两个世界坐标变换矩阵,这时需要将第一个参数设置为D3DTS_WORLDMATRIX宏,第二个参数设置为相应的混合变换矩阵。
在对顶点位置和法线进行混合时,每个混合矩阵对最终的顶点位置和法线的影响大小由混合权重来决定。混合权重是0.0 ~
1.0之间的浮点数,0.0表示该权重对应的混合矩阵对顶点位置和法线向量没有影响,1.0表示顶点的位置和法线完全通过该权重对应的混合矩阵进行变换,权重也是顶点数据的一部分。
Direct3D根据混合矩阵和相应的权重对顶点位置和法线进行现行插值,公式如下:
Vblend = V * (M0
* W0 + M1 * W1 + ... + Mn * Wn)
其中,Vblend表示混合后的顶点,V表示混合前的顶点,M0、M1、...,Mn表示混合矩阵,W0、W1、...,Wn表示混合权重。
因为所有混合权重之和为1.0,所以在顶点数据中只需保存前n-1个混合权重,第n个混合权重为1.0减去前n-1个混合权重之和。在Direct3D引擎中,影响每个顶点的混合矩阵最大数量限定为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)))
如果使用图形混合,则在顶点数据中必须包含相应的混合权重数据,尽管在灵活顶点格式中使用D3DFVF_XYZB1 ~
D3DFVF_XYZB5指定顶点数据中最多可以包含5个混合权重,但目前的Direct3D版本最多只使用前面三个混合权重。在具体渲染图形时,Direct3D使用几个混合矩阵和相应的混合权重对顶点进行混合,由渲染状态D3DVERTEXBLEND控制,该渲染状态的取值为枚举类型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.
在默认情况下,顶点混合是禁用的。要启用图形混合功能,只需调用IDirect3DDevice9::SetRenderState()函数,将渲染状态D3DVERTEXBLEND设置为D3DVERTEXBLENDFLAGS枚举值中除D3DVBF_DISABLE外的其他值。如果启用了图形混合功能,Direct3D就认为在顶点数据中包含了合适数量的混合权重,程序员的工作就是为图形渲染提供包含所需数量混合权重的顶点数据和相应的顶点格式。