灵活顶点格式(Flexible Vertex Format, FVF)用来描述在顶点缓冲区中的顶点存储格式中包含了哪些属性。Direct3D应用程序可以用几种不同的方式定义灵活顶点格式。灵活顶点格式使应用程序只使用它需要的顶点数据,排除那些它不需要的组成成分。这样,应用程序可以节省内存空间,减少系统带宽。通过D3DFVF的组合,可以描述图元顶点的格式。灵活顶点格式指定的格式包括点的大小,用D3DFVF_PSIZE指定,该大小在投影机空间用来表示未经变换的顶点,在设备空间用来表示经过变换的顶点。
接口IDirect3DDevice9的渲染方法能够接受这些标志的组合,并用它们来决定如何渲染图元。这些标志告诉系统应用程序所使用的顶点的组成,包括顶点的位置、顶点混合权重、法向量、颜色和纹理坐标的格式和数量,以及向Direct3D申请何种渲染流水线。另外,提交或撤销一个具体的顶点格式标志会告诉系统哪些顶点组成单元还留在系统中,哪些已经被忽略了。
定义顶点格式:
{
FLOAT x,y,z,rhw;
DWORD color;
};
注: RHW表示投影空间中顶点所在的齐次点(x,y,z,w)(homogeneous point)的w坐标的导数(reciprocal), 更详细说明请看:http://www.cnblogs.com/xmzyl/articles/1604150.html
还需要定义一个宏,来向D3D说明一下,指定定义的顶点格式有哪些。
上面这一句话的意思就是,定义的顶点结构包含:位置变换信息(D3DFVF_XYZRHW)和漫反射颜色信息(D3DFVF_DIFFUSE);那么,一共都有哪些类型可以定义呢,都有什么样的用呢。
define | Description | Data order and type |
---|---|---|
D3DFVF_DIFFUSE | 让顶点信息包含漫反射颜色的信息,在希望顶点有颜色的时候使用,比如一般教程的开始都会画一个有颜色的三角形,那时必须要包含这个信息 | DWORD in ARGB order. See D3DCOLOR_ARGB. |
D3DFVF_NORMAL | 让顶点包含法线信息,这个标志不能和 D3DFVF_XYZRHW 一块使用(为什么呢,请见下面)。法线信息,对于一个面来说就是和这个面相互垂直的一个向量(指向面的正面),而对于一个点来说,包含这个点的面是共面的的话,和面的法向量相同,如果不共面的话,是面的法向量的和向量。 | 类型是 :float, float, float |
D3DFVF_PSIZE | 让顶点拥有这么一个特性:顶点的大小是一个像素点,并且大小不随相机的位置变化而变化。还没用过这个只是猜测。 | float |
D3DFVF_SPECULAR | 让顶点拥有镜面反射颜色的信息。(和漫反射类似,不过这个的计算量很大) | DWORD in ARGB order. See D3DCOLOR_ARGB. |
D3DFVF_XYZ | 让顶点包含位置信息,这个和D3DFVF_XYZRHW不可共用,用D3DFVF_XYZ标志的顶点会参与D3D渲染时候的一系列的变换操作(包括世界矩阵的变换,取景变换等等。) | float, float, float. |
D3DFVF_XYZRHW | 同上面的参数有些类似,但是最大的区别是,用这个参数定义的顶点的位置,不会参与D3D的所有变换,也就意味着x,y坐标就是屏幕上的点的坐标,z暂时没有什么用处,可能是用于雾化那一块的,还没有测试。 | float, float, float, float. |
D3DFVF_XYZB1 through D3DFVF_XYZB5 | Vertex format contains position data, and a corresponding number of weighting (beta) values to use for multimatrix vertex blending operations. Currently, Direct3D can blend with up to three weighting values and four blending matrices. For more information about using blending matrices, see Indexed Vertex Blending (Direct3D 9). | 1, 2, or 3 floats. When D3DFVF_LASTBETA_UBYTE4 is used, the last blending weight is treated as a DWORD. |
D3DFVF_XYZW | 这个数据和D3DFVF_XYZW相似,也是位置关系,但是它的作用是标志这个点已经经过了投影变换,所以D3D对其不再进行投影变换,猜测而已,具体还需验证。 | float, float, float, float |
#define | Description |
---|---|
D3DFVF_TEX0 - D3DFVF_TEX8 | 0--8层的纹理,让顶点具有纹理坐标的信息 |
D3DFVF_TEXCOORDSIZEN(coordIndex) | Define a texture coordinate data set. n indicates the dimension of the texture coordinates. coordIndex indicates texture coordinate index number. See D3DFVF_TEXCOORDSIZEN and Texture coordinates and Texture Stages. |
#define | Description |
---|---|
D3DFVF_POSITION_MASK | Mask for position bits. |
D3DFVF_RESERVED0, D3DFVF_RESERVED2 | Mask values for reserved bits in the FVF. Do not use. |
D3DFVF_TEXCOUNT_MASK | Mask value for texture flag bits. |
#define | Description |
---|---|
D3DFVF_LASTBETA_D3DCOLOR | The last beta field in the vertex position data will be of type D3DCOLOR. The data in the beta fields are used with matrix palette skinning to specify matrix indices. |
D3DFVF_LASTBETA_UBYTE4 | The last beta field in the vertex position data will be of type UBYTE4. The data in the beta fields are used with matrix palette skinning to specify matrix indices. // Given the following vertex data definition: Given the FVF is declared as: D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4. Weight and MatrixIndices are included in beta[5], where D3DFVF_LASTBETA_UBYTE4 says to interpret the last DWORD in beta[5] as type UBYTE4. |
D3DFVF_TEXCOUNT_SHIFT | The number of bits by which to shift an integer value that identifies the number of texture coordinates for a vertex. This value might be used as shown below. DWORD dwNumTextures = 1; // Vertex has only one set of coordinates.
|
值得注意的是,D3DFVF_XYZRHW和D3DFVF_XYZ、D3DFVF_NORMAL不能共存,因为后两个标志与前一个矛盾。在使用这种顶点时,系统需要顶点的位置已经经过变换了。
在定义完顶点格式以后,就要开辟一块顶点缓冲区:
0 ,
D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT,
& g_pVB, NULL )
开辟缓冲区后,就需要对这个缓冲区进行填写,那么填写的数据呢,也需要先指定出来:
{ 100.0f , 400.0f , 0.5f , 1.0f , 0xffff0000 , },
{ 300.0f , 50.0f , 0.5f , 1.0f , 0xff00ff00 , },
{ 500.0f , 400.0f , 0.5f , 1.0f , 0xff0000ff , },
};
然后将数据写入缓冲区:
if ( FAILED( g_pVB -> Lock( 0 , sizeof (vertices), ( void ** ) & pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, vertices, sizeof (vertices) );
g_pVB -> Unlock();
这里写入的过程用的是Lock函数得到的缓冲区的地址,然后用memcpy函数将自己写好的数据写进去。到这里,顶点就算是创建好了。