码迷,mamicode.com
首页 > 其他好文 > 详细

DirectX3D开发之绘制第一个图形

时间:2015-08-28 17:35:14      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:directx3d开发

   欢迎访问EasyLiu的博客!

   在前一章节我们已经创建了我们的第一个DirectX3D项目,但是只是显示一个灰色的窗口而已,并没有进行相应的

绘图操作。那么今天,我们就来让窗口变得更漂亮一些。

   今天主要讲通过顶点缓冲区绘制图形。什么是顶点缓冲区?顶点缓冲区就是用来保存顶点数据的内存缓冲区,在DirectX3D中由COM接口IDirectVertexBuffer9表示,顶点缓冲区中顶点的数据就决定了渲染到屏幕上的效果。

LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices

   顶点数据可以包含坐标、颜色等属性,而具体使用什么属性,可以使用灵活顶点格式(FVF)规定顶点的格式。FVF中包含了多种属性,我们可以根据我们的需要来定义我们的顶点数据格式,以逻辑或(|)连接即可,如下:

// A structure for our custom vertex type
struct CUSTOMVERTEX
{
	FLOAT x, y, z, rhw; // The transformed position for the vertex
	DWORD color;        // The vertex color
};

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
    这里我们定义了自己的顶点格式,其中包括D3DFVF_XYZRHW(经过转换后的坐标)和D3DFVF_DIFFUSE(漫反射)。在顶点结构体中没有RHW时,Direct3D将执行视、投影、世界等变换以及进行光线计算,之后你才能在窗口中得到你所绘制的物体,这个在下一节仔细讲当顶点结构体中有RHW时,告知Direct3D使用的顶点已经在屏幕坐标系中了,不再执行视图、投影、世界等变换和光线计算,因为D3DFVF_XYZRHW标志告诉它顶点已经经过了这些处理,并直接将顶点进行光栅操作,任何用SetTransform进行的转换都对其无效。不过这时的原点就在客户区的左上角了,其中x向右为正,y向下为正,而z的意义已经变为z-buffer的象素深度。值得注意的是D3DFVF_XYZRHW和D3DFVF_XYZ、D3DFVF_NORMAL不能共存,因为后两个标志与前一个矛盾。

    定义了顶点格式之后,我们就来初始化我们的顶点缓冲区。这里,定义了一个初始化函数InitVB:

HRESULT InitVB()
{
	// Initialize three vertices for rendering a triangle
	CUSTOMVERTEX vertices[] =
	{
		{ 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
		{ 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00,},
		{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
	};

	// Create the vertex buffer. Here we are allocating enough memory
	// (from the default pool) to hold all our 3 custom vertices. We also
	// specify the FVF, so the vertex buffer knows what data it contains.
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(3 * sizeof(CUSTOMVERTEX),
		0, D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT, &g_pVB, NULL)))
	{
		return E_FAIL;
	}

	// Now we fill the vertex buffer. To do this, we need to Lock() the VB to
	// gain access to the vertices. This mechanism is required becuase vertex
	// buffers may be in device memory.
	VOID* pVertices;
	if (FAILED(g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, vertices, sizeof(vertices));
	g_pVB->Unlock();
	return S_OK;
}

    在InitVB中,首先定义图形的顶点,在此我们初始化了一个三角形的三个顶点,存放在vertices数组中(注意:顶点的填充顺序与裁剪方式有关,默认是顺时针,可以通过g_pDevice->SetRenderState(…)进行设置,以后我们会进行讲解)。g_pDevice是有效的DirectX3D设备指针,CreateVertexBuffer方法就是创建顶点缓冲区的方法,第一个参数表示要创建的顶点缓冲区的大小(字节数),在此我们设置为数组的大小;第二个参数表示顶点缓冲区的属性,在此设置为0;第三个参数表示灵活顶点格式,设置为定义好的CUSTOMVERTEX;第四个参数表示顶点缓冲区内存类型,从枚举类型D3DPOOL(内存池)中选择,在此选择默认类型D3DPOOL_DEFAULT();第五个参数就是顶点缓冲区接口的地址;第六个参数是保留参数,在此设置为NULL。

    顶点缓冲区创建好了之后,我们需要将vertexes中的数据填充进去,这时,我们需要两个函数:Lock()、Unlock()。在对顶点缓冲区进行修改时,必须先后调用加锁与解锁方法,然后通过memcpy方法,将数据拷贝到缓冲区中即可。

到此,顶点缓冲区就初始化完毕了。然后在消息循环之前调用此方法以使顶点缓冲区有效。

再就是Render()方法,

VOID Render()
{
	// Clear the backbuffer to a blue color
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);

	// Begin the scene
	if (SUCCEEDED(g_pd3dDevice->BeginScene()))
	{
		// Draw the triangles in the vertex buffer. This is broken into a few
		// steps. We are passing the vertices down a "stream", so first we need
		// to specify the source of that stream, which is our vertex buffer. Then
		// we need to let D3D know what vertex shader to use. Full, custom vertex
		// shaders are an advanced topic, but in most cases the vertex shader is
		// just the FVF, so that D3D knows what type of vertices we are dealing
		// with. Finally, we call DrawPrimitive() which does the actual rendering
		// of our geometry (in this case, just one triangle).
		g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
		//The first parameter accepted by DrawPrimitive is a flag that tells Direct3D what type of primitives to draw
		//This sample uses the flag D3DPT_TRIANGLELIST to specify a list of triangles. 
		//The second parameter is the index of the first vertex to load.
		//The third parameter tells the number of primitives to draw.
		//Because this sample draws only one triangle, this value is set to 1.
		//g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
		g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

		// End the scene
		g_pd3dDevice->EndScene();
	}

	// Present the backbuffer contents to the display
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}

Render()方法主要调用了三个方法SetStreamSource、SetFVF、DrawPrimitive。

SetStreamSource方法的作用是将顶点缓冲区与渲染数据流连接起来,第一个参数表示与顶点缓冲区链接的渲染数据流的编号(>=0);第二个参数表示顶点缓冲区接口指针;第三个参数表示渲染数据流的起始位置;第四个参数表示相邻顶点距离的字节数,在此为VERTEX结构体CUSTOMVERTEX的大小。

SetFVF方法设置渲染数据流的灵活顶点格式,在此设置自己定义的CUSTOMVERTEX。

DrawPrimitive就是用来绘制渲染数据流中图元的方法。其中有三个参数,分别为,第一个参数表示渲染的图元类型,在此为D3DPT_TRIANGLELIST(三角形列表);第二个参数表示从顶点缓冲区的第几个顶点开始绘制;第三个参数表示绘制的图元的数量。

最后别忘了在Cleanup方法中将g_pVB接口Release掉,

VOID Cleanup()
{
	if (g_pVB != NULL)
		g_pVB->Release();

	if (g_pd3dDevice != NULL)
		g_pd3dDevice->Release();

	if (g_pD3D != NULL)
		g_pD3D->Release();
}

保存修改,按Ctrl+F5运行项目,效果如下:

技术分享





版权声明:本文为博主原创文章,未经博主允许不得转载。

DirectX3D开发之绘制第一个图形

标签:directx3d开发

原文地址:http://blog.csdn.net/liuyi1207164339/article/details/48054705

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!