前面章节我们已经创建了我们的第一个DirectX3D项目,以及对DirectX3D的基本图元有了相应的了解,到现在为止,我们的项目还只是一个蓝色的窗口,似乎没什么让人感到兴奋的。那今天,我们就来为我们的项目添加一些内容,让我们的窗口变得“漂亮”一点。
今天我们主要讲通过顶点缓冲区绘制图形,首先,先要知道,什么是顶点缓冲区,顶点缓冲区就是用来保存顶点数据的内存缓冲区,在DirectX3D中由COM接口IDirectVertexBuffer9表示,顶点缓冲区中顶点的数据就决定了渲染到屏幕上的效果。
1 2 3 |
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; |
顶点数据可以包含坐标、颜色等属性,而具体使用什么属性,可以使用灵活顶点格式(FVF)规定顶点的格式。FVF中包含了多种属性,我们可以根据我们的需要来定义我们的顶点数据格式,以逻辑或(|)连接即可,如下:
1 2 3 4 5 6 7 8 |
#define FVF D3DFVF_XYZRHW ¦ D3DFVF_DIFFUSE struct VERTEX { float x, y, z, rhw; DWORD color; }; |
我们定义了自己的顶点格式,其中包括D3DFVF_XYZRHW(经过转换后的坐标)和D3DFVF_DIFFUSE(漫反射)。需要注意的一点是,这里用的D3DFVF_XYZRHW不能和D3DFVF_XYZ、D3DFVF_NORMAL同时使用,因为D3DFVF_XYZRHW是经过转换后的顶点坐标,与后两者冲突。在定义顶点结构VERTEX的时候,不只是要与定义的灵活顶点格式相符,还要与DirectX3D给出的属性顺序相符:位置(如:x、y、z),RHW(Reciprocal of the Homogenous W,即1/W),混合加权,顶点法线,顶点大小,漫反射,镜面反射,纹理坐标。
定义了我们的顶点格式,下面就来初始化一下我们的顶点缓冲区,在此,我定义了一个InitVB方法,用来放置我们的初始化代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
HRESULT InitVB() { VERTEX vertexes[] = { { 0.0f, 200.0f, 1.0f, 1.0f, 0xff112233 }, { 150.0f, 0.0f, 1.0f, 1.0f, 0xff224488 }, { 300.0f, 200.0f, 1.0f, 1.0f, 0xff789034 } }; if (FAILED(g_pDevice->CreateVertexBuffer( sizeof(vertexes) , 0 , FVF , D3DPOOL_DEFAULT , &g_pVB , NULL ))) { return E_FAIL; } void *pvertexes = NULL; if (FAILED(g_pVB->Lock(0, sizeof(vertexes), (void**)&pvertexes, 0))) { return E_FAIL; } memcpy(pvertexes, vertexes, sizeof(vertexes)); g_pVB->Unlock(); return S_OK; } |
在InitVB中,首先定义图形的顶点,在此我们初始化了一个三角形的三个顶点,存放在vertexes数组中(注意:顶点的填充顺序与裁剪方式有关,默认是顺时针,可以通过g_pDevice->SetRenderState(…)进行设置,以后我们会进行讲解)。g_pDevice是有效的DirectX3D设备指针,CreateVertexBuffer方法就是创建顶点缓冲区的方法,第一个参数表示要创建的顶点缓冲区的大小(字节数),在此我们设置为数组的大小;第二个参数表示顶点缓冲区的属性,在此设置为0;第三个参数表示灵活顶点格式,设置为定义好的FVF;第四个参数表示顶点缓冲区内存类型,从枚举类型D3DPOOL中选择,在此选择默认类型D3DPOOL_DEFAULT(顶点缓冲区尽可能存放在显存中,设备丢失时,数据会丢失);第五个参数就是顶点缓冲区接口的地址;第六个参数是保留参数,在此设置为NULL。
顶点缓冲区创建好了之后,我们需要将vertexes中的数据填充进去,这时,我们需要两个函数:Lock()、Unlock()。在对顶点缓冲区进行修改时,必须先后调用加锁与解锁方法,然后通过memcpy方法,将数据拷贝到缓冲区中即可。
到此,顶点缓冲区就初始化完毕了。然后在消息循环之前调用此方法以使顶点缓冲区有效。
再就是Render()方法,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void Render() { if (NULL == g_pDevice) { return; } g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(30, 60, 90), 1.0f, 0); if (SUCCEEDED(g_pDevice->BeginScene())) { g_pDevice->SetStreamSource(0, g_pVB, 0, sizeof(VERTEX)); g_pDevice->SetFVF(FVF); g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); g_pDevice->EndScene(); } g_pDevice->Present(NULL, NULL, NULL, NULL); } |
Render()方法主要调用了三个方法SetStreamSource、SetFVF、DrawPrimitive。
SetStreamSource方法的作用是将顶点缓冲区与渲染数据流链接起来,第一个参数表示与顶点缓冲区链接的渲染数据流的编号(>=0);第二个参数表示顶点缓冲区接口指针;第三个参数表示渲染数据流的起始位置;第四个参数表示相邻顶点距离的字节数,在此为VERTEX结构体的大小。
SetFVF方法设置渲染数据流的灵活顶点格式,在此设置自己定义的FVF。
DrawPrimitive就是用来绘制渲染数据流中图元的方法。其中有三个参数,分别为,第一个参数表示渲染的图元类型,在此为D3DPT_TRIANGLELIST(三角形列表);第二个参数表示从顶点缓冲区的第几个顶点开始绘制;第三个参数表示绘制的图元的数量。
最后别忘了在Cleanup方法中将g_pVB接口Release掉,
1 2 3 4 5 6 |
if (NULL != g_pVB) { g_pVB->Release(); } |
保存修改,按Ctrl+F5运行项目,效果如下:
以上仅供参考,如有不足还望不吝赐教,ZXGoto祝大家编程愉快!
源码下载地址:http://115.com/file/c2l6hhpk#sample(绘制第一个图形).zip
- 本文固定链接: https://www.xuanyusong.com/archives/869
- 转载请注明: ZXGoto 于 雨松MOMO程序研究院 发表
你好,为什么我下载不了呢
Momo,你好。 装DirectX的时候就显示1023的错误码。网上查了是说我本机已经有高版本的这个Microsoft Visual C 2010 x86 Redistributable – 1010.0.40219。于是我卸载了怎么安装还是一样。测试了你的第一个demo是可以的。但是第二个demo就显示不出三角形了。是不是DirectX安装的还是有问题?
Momo,你好。 装DirectX的时候就显示1023的错误码。网上查了是说我本机已经有高版本的这个Microsoft Visual C++ 2010 x86 Redistributable – 1010.0.40219。于是我卸载了怎么安装还是一样。测试了你的第一个demo是可以的。但是第二个demo就显示不出三角形了。是不是DirectX安装的还是有问题?
靠,少传了点东西。。。
多谢支持,努力
加油啦
支持下 ZXGOTO
哈,