三、图形绘制
前面的程序框架可以生成一个不含任何图形的背景图像,下面介绍的是如何显示一个基本的图形。D3D中定义了6种基本的图形表示,称为图元。
图元类型 | D3D表示 | 意义 |
顶点集合 | D3DPT_POINTLIST | 一组点的集合 |
线段集合 | D3DPT_LINELIST | 一组线段的组合 |
首尾相接形式的线段集合 | D3DPT_LINESTRIP | 以不间断点表示的一组线段 |
三角形集合 | D3DPT_TRIANGLELIST | 一组三角形组合 |
首尾相接形式的三角形集合 | D3DPT_TRIANGLESTRIP | 以不间断点表示的一组三角形 |
扇形形式的三角形集合 | D3DPT_TRIANGLEFAN | 用扇形表示的一组三角形 |
绘制方法,以使用顶点缓冲区来绘制图形为例。
1、创建一个顶点缓冲区
这里有两个重要概念,顶点缓冲区和FVF(Flexible Vertex Format)。顶点缓冲区是D3D用来保存顶点数据的内存缓冲区,可以保存任何类型的顶点信息,由IDirect3DVertexBuffer9对象接口表示。
FVF是用来描述顶点缓冲区中的顶点存放格式,包含坐标,颜色,法线方向,纹理坐标等,它的值可以使用|进行组合,具体值可参见开发文档。这里给出一个简单示例:
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
D3DFVF_XYZRHW表示顶点格式包含经过坐标转换的顶点坐标(与D3DFVF_XYZ相对应,D3DFVF_XYZ是未经转换的)
D3DFVF_DIFFUSE是顶点格式包含的漫反射颜色值
注意,这里定义的宏D3DFVF_CUSTOMVERTEX中的FVF值组合必须与下面定义的顶点信息结构体的含义保持一致。
typedef struct _StrCUSTOMVERTEX
{
FLOAT x, y, z, rhw;//三角形顶点在投影矩阵中的坐标值,rhw为投影矫正系数
DWORD color;
}CUSTOMVERTEX;
IDirect3DDevice9:: CreateVertexBuffer()就是顶点缓冲区创建函数,参数说明参见后面的示例代码。
2、顶点数据拷贝
对顶点缓冲区的内存操作必须通过IDirect3DVertexBuffer9::Lock()和IDirect3DVertexBuffer9::Unlock()来实现,即对顶点缓冲区进行加锁和解锁操作。默认情况下,D3D系统在lock执行时会暂停其它的显示操作。可以设置加锁属性来使其它操作同时执行。示例代码如下:
LPDIRECT3DVERTEXBUFFER9 g_pVB;
HRESULT Cdig_D3DDlg::InitVB()//D3DXCreateTextureFromFile
{
CUSTOMVERTEX g_Vertices[] =
{
{50.0f,50.0f,0.5f,1.0f,0xffff0000},
{150.0f,150.0f,0.5f,1.0f,0xff00ff00},
{50.0f,150.0f,0.5f,1.0f,0xff00ffff},
};
// Create the vertex buffer
//3*sizeof(CUSTOMVERTEX):缓冲区大小
//顶点缓冲区属性
//FVF
//D3DPOOL_DEFAULT:指定顶点缓冲区资源内存位置的枚举变量
//顶点缓冲区指针
//保留参数
if (FAILED(g_pd3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT,/
&g_pVB, NULL)))
{
return E_FAIL;
};
VOID *pVertices;
//0:加锁内存的起始位置
//sizeof(g_Vertices):加锁内存的大小
//(void**)&pVertices:返回内存指针的地址
//0:加锁属性
if(FAILED(g_pVB->Lock(0, sizeof(g_Vertices), (void**)&pVertices,0)))
return E_FAIL;
memcpy(pVertices, g_Vertices, sizeof(g_Vertices));
g_pVB->Unlock();
return S_OK;
};
3、顶点缓冲区图形显示
在前面程序Render函数的g_pd3dDevice->BeginScene()和g_pd3dDevice->EndScene()之间加入以下三个函数就可以实现图形的显示:
IDirect3DDevice9:: SetStreamSource()是链接顶点缓冲区和渲染数据流
IDirect3DDevice9:: SetFVF()是指定当前渲染数据流中的FVF
IDirect3DDevice9:: DrawPrimitive是用来绘制当前的渲染数据流中的图元至后台
示例代码如下,可以绘制出一个三角形:
g_pd3dDevice->BeginScene();
//0:渲染数据流序号
//g_pVB:进行绑定的顶点缓冲区指针
//0:进行绑定的渲染数据流的起始位置
//sizeof(CUSTOMVERTEX):单位顶点的大小
g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
//图元类型
//绘制的顶点起始索引值
//绘制的图元数量
// g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
g_pd3dDevice->EndScene();
另外一种绘制图形的方法是使用索引缓冲区,目的在于减少重复的顶点坐标,因为方法类似这里就不赘述了!