DirectX9例程:绘制简单立方体

总结至红龙书提供的立方体绘制例程代码及重要函数:

 

d3dUtility.h

#ifndef __d3dUtilityH__  
#define __d3dUtilityH__  

#include <d3dx9.h>   

namespace d3d
{
	//初始化DirectX3D
	bool InitD3D(                     
		HINSTANCE hInstance,       // [in] Application instance 
		int width, int height,     // [in] Backbuffer dimensions
		bool windowed,             // [in] Windowed (true)or full screen (false)
		D3DDEVTYPE deviceType,     // [in] HAL or REF  
		IDirect3DDevice9** device);// [out]The created device

        //消息循环
	int EnterMsgLoop(   
		bool(*ptr_display)(float timeDelta));

	LRESULT CALLBACK Wnd_Proc(
		HWND hwnd,
		UINT msg,
		WPARAM wParam,
		LPARAM lParam);

	template<class T> void Release(T t)
	{
		if (t)
		{
			t->Release();
			t = 0;
		}
	}

	template<class T> void Delete(T t)
	{
		if (t)
		{
			delete t;
			t = 0;
		}
	}
}

#endif 

 

d3dUtility.cpp

#include "d3dUtility.h"
//#pragma comment(lib,"d3d9.lib")  
//#pragma comment(lib,"d3dx9.lib")  
//#pragma comment(lib,"winmm.lib")  

bool d3d::InitD3D(
	HINSTANCE hInstance,
	int width, int height,
	bool windowed,
	D3DDEVTYPE deviceType,
	IDirect3DDevice9** device)
{
	//  
	// Create the main application window.  
	//  

	WNDCLASS wc;

	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = (WNDPROC)d3d::Wnd_Proc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(0, IDI_APPLICATION);
	wc.hCursor = LoadCursor(0, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName = 0;
	wc.lpszClassName = "Direct3D9App";

	if (!RegisterClass(&wc))
	{
		::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
		return false;
	}
	     
	HWND hwnd = 0;
	hwnd = ::CreateWindow(
		"Direct3D9App", 
		"Direct3D9App",
		WS_EX_APPWINDOW,
		0, 0, width, height,
		0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/);

	//HWND CreateWindow(            
	//  LPCTSTR lpWindowName,      // 窗口标题
	//  DWORD dwStyle,             // 窗口风格
	//  int x,                     // 初始 x 坐标
	//  int y,                     // 初始 y 坐标
	//  int nWidth,                // 初始 x 方向尺寸
	//  int nHeight,               // 初始 y 方向尺寸
	//  HWND hWndParent,           // 父窗口句柄
	//  HMENU hMenu,               // 窗口菜单句柄
	//  HINSTANCE hInstance,       // 程序实例句柄
	//  LPVOID lpParam             // 创建参数
	//); 

	if (!hwnd)
	{
		::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
		return false;
	}

	::ShowWindow(hwnd, SW_SHOW);
	::UpdateWindow(hwnd);


	// Init D3D:    

	HRESULT hr = 0;
 
	//要初始化IDirect3D,首先必须获取指向接口IDrect3D9的指针。使得一个专门的Direct3D函数可以很容易做到  
	IDirect3D9* d3d9 = 0;
	d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

	if (!d3d9)
	{
		::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
		return false;
	}
 
	//检验图形卡是否支持该硬件顶点运算  
	D3DCAPS9 caps;
	d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);

	int vp = 0;
	if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
		//硬件顶点运算
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;  
	else
		//软件顶点运算
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;  
	 
	//填充D3DPRESENT_PARAMETERS结构体
	D3DPRESENT_PARAMETERS d3dpp;
	d3dpp.BackBufferWidth = width;                 //后台缓存中表面的宽度,单位为像素  
	d3dpp.BackBufferHeight = height;               //后台缓存中表面的高度,单位为像素  
	d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;      //后台缓存的像素格式(如32位像素格式:D3DFMT_A8R8G8B8)  
	d3dpp.BackBufferCount = 1;                     //所需使用的后台缓存的个数,通常是1,需要一个后台缓存  
	d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;   //多重采样类型  
	d3dpp.MultiSampleQuality = 0;                  //多重采样的质量水平  
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;      //枚举类型指定交换链中的缓存的页面设置方式。  
	d3dpp.hDeviceWindow = hwnd;                    //与设备相关的窗口句柄。指定了所有进行绘制的应用程序窗口  
	d3dpp.Windowed = windowed;                     //窗口模式,为false时表示全屏模式
	d3dpp.EnableAutoDepthStencil = true;           //为true时,自动创建并维护深度缓存或模板缓存  
	d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;   //深度缓存或模板缓存的像素格式  
	d3dpp.Flags = 0;                               //附加特性 
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;   //刷新频率
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;   //一般为立即提交或由Direct3D来选择提交
 
	// 创建IDrect3Device9接口
	hr = d3d9->CreateDevice(
		D3DADAPTER_DEFAULT,  
		deviceType,           
		hwnd,                
		vp,                
		&d3dpp,              
		device);             

	//HRESULT CreateDevice(
    //    UINT Adapter,                                    // 希望代表的物理显卡
    //    D3DDEVTYPE DeviceType,                           // 设备类型
	//    HWND hFocusWindow,                               // 窗口句柄,指设备要绘制的目标窗口 
	//    DWORD BehaviorFlags,                             // 顶点运算类型
	//    D3DPRESENT_PARAMETERS *pPresentationParameters,  // 完成初始化的D3DPRESENT_PARAMETERS结构体
	//    IDirect3DDevice9 **ppReturnedDeviceInterface     // 返回所创建的设备
	//);

	if (FAILED(hr))
	{
		// 再次使用16位深度缓存尝试 
		d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

		hr = d3d9->CreateDevice(
			D3DADAPTER_DEFAULT,
			deviceType,
			hwnd,
			vp,
			&d3dpp,
			device); 

		if (FAILED(hr))
		{
			d3d9->Release();  
			::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
			return false;
		}
	}

	d3d9->Release();  

	return true;
}

//消息循环  
int d3d::EnterMsgLoop(bool(*ptr_display)(float timeDelta))
{
	MSG msg;
	::ZeroMemory(&msg, sizeof(MSG));

	static float lastTime = (float)timeGetTime();

	while (msg.message != WM_QUIT)
	{
		if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}
		else
		{
			float currTime = (float)timeGetTime();
			//计算相邻两次调用ptr_display的时间间隔 
			float timeDelta = (currTime - lastTime)*0.001f;
			//调用指定display函数
			ptr_display(timeDelta);

			lastTime = currTime;
		}
	}
	return msg.wParam;
}

 

DirectXDrawCube.cpp

#include "d3dUtility.h"

//初始化设备
IDirect3DDevice9* device = NULL;

//初始化顶点缓存和索引缓存
IDirect3DVertexBuffer9* VB = 0;
IDirect3DIndexBuffer9* IB = 0;

//定义屏幕分辨率
const int width = 640;
const int height = 480;

//定义顶点结构和灵活顶点格式
typedef struct Vertex {
	Vertex() {}
	Vertex(float x, float y, float z) {
		_x = x;
		_y = y;
		_z = z;
	}

	float _x, _y, _z;
	static const DWORD FVF;  //灵活顶点格式
    
}vertex;
const DWORD vertex::FVF = D3DFVF_XYZ;

//setup
bool setup()
{
	//创建顶点缓存
	device->CreateVertexBuffer(8 * sizeof(vertex), D3DUSAGE_WRITEONLY, vertex::FVF, D3DPOOL_MANAGED, &VB, 0);
	//HRESULT CreateVertexBuffer(
	//	  UINT Length,                                //为缓存分配的字节数  
	//	  DWORD Usage,                                //顶点缓冲区的附加属性,D3DUSAGE_WRITEONLY为"只写"  
	//	  DWORD FVF,                                  //灵活顶点格式  
	//	  D3DPOOL Pool,                               //顶点缓冲的内存池  
	//	  IDirect3DVertexBuffer9** ppVertexBuffer,    //顶点缓冲指针  
	//	  HANDLE* pSharedHandle                       //保留参数,置为0  
	//);

	//创建索引缓存
	device->CreateIndexBuffer(36 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16/*索引大小*/, D3DPOOL_MANAGED, &IB, 0);

	//填充顶点缓存
	vertex* vertices;
	VB->Lock(0, 0, (void**)&vertices, 0);

	vertices[0] = vertex(-1.0f, -1.0f, -1.0f);
	vertices[1] = vertex(-1.0f,  1.0f, -1.0f);
	vertices[2] = vertex( 1.0f,  1.0f, -1.0f);
	vertices[3] = vertex( 1.0f, -1.0f, -1.0f);
	vertices[4] = vertex(-1.0f, -1.0f,  1.0f);
	vertices[5] = vertex(-1.0f,  1.0f,  1.0f);
	vertices[6] = vertex( 1.0f,  1.0f,  1.0f);
	vertices[7] = vertex( 1.0f, -1.0f,  1.0f);

	VB->Unlock();

	//填充索引缓存
	WORD* indices = 0;
	IB->Lock(0, 0, (void**)&indices, 0);

	indices[ 0] = 0; indices[ 1] = 1; indices[ 2] = 2;
	indices[ 3] = 0; indices[ 4] = 2; indices[ 5] = 3;

	indices[ 6] = 4; indices[ 7] = 6; indices[ 8] = 5;
	indices[ 9] = 4; indices[10] = 7; indices[11] = 6;

	indices[12] = 4; indices[13] = 5; indices[14] = 1;
	indices[15] = 4; indices[16] = 1; indices[17] = 0;

	indices[18] = 3; indices[19] = 2; indices[20] = 6;
	indices[21] = 3; indices[22] = 6; indices[23] = 7;

	indices[24] = 1; indices[25] = 5; indices[26] = 6;
	indices[27] = 1; indices[28] = 6; indices[29] = 2;

	indices[30] = 4; indices[31] = 0; indices[32] = 3;
	indices[33] = 4; indices[34] = 3; indices[35] = 7;

	IB->Unlock();

	//创建观察坐标系变换矩阵并设定变换
	D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
	D3DXMATRIX v;
	D3DXMatrixLookAtLH(&v, &position, &target, &up);
	device->SetTransform(D3DTS_VIEW, &v);

	//创建投影变换矩阵并设定变换
	D3DXMATRIX projection;
	D3DXMatrixPerspectiveFovLH(&projection, D3DX_PI*0.5f, (float)width / (float)height, 1.0, 1000.0f);
	device->SetTransform(D3DTS_PROJECTION, &projection);

	//设定绘制状态为线框模式
	device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

	return true;
}

//cleanup
void cleanup()
{
	// 释放顶点缓存和索引缓存
	d3d::Release<IDirect3DVertexBuffer9*>(VB);
	d3d::Release<IDirect3DIndexBuffer9*>(IB);
}

//display
bool display(float timeDelta)
{
	if (device == NULL)
		return false;
	
	//平移矩阵
	D3DXMATRIX translation;
	
	static float tx = -3.0f;
	static float ty = 0.0f;
	static const float multi = 1.0f;
	static float multix = multi;
	static float multiy = multi;

	tx += multix*timeDelta;
	ty += multiy*timeDelta;

    D3DXMatrixTranslation(&translation, tx, ty, 0);

	if (tx >= 3.0f)
		multix = -1.0f*multi;
	else if (tx <= -3.0f)
		multix = 1.0f*multi;
	
	if (ty >= 3.0f)
		multiy = -1.0f*multi;
	else if (ty <= -3.0f)
		multiy = 1.0f*multi;

	//旋转矩阵
	D3DXMATRIX rotationXM, rotationYM;

	static float r = 0.0f;
	D3DXMatrixRotationX(&rotationXM, r);
	D3DXMatrixRotationY(&rotationYM, r);
	r += timeDelta;

	if (r >= 6.28)
		r = 0.0f;

	D3DXMATRIX p = rotationXM*rotationYM*translation;
	device->SetTransform(D3DTS_WORLD, &p);

	
	device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
	//HRESULT Clear(
	//	  DWORD Count,                 //pRects数组中矩形的数目
	//	  const D3DRECT *pRects,       //所要执行清除操作的屏幕矩形数组
	//	  DWORD Flags,                 //所要清除的表面,包括D3DCLEAR_TARGET(后台缓存), D3DCLEAR_ZBUFFER(Z深度缓存), D3DCLEAR_STENCIL(模板平面缓存)
	//	  D3DCOLOR Color,              //指定将绘制目标体设置为何种颜色
	//	  float Z,                     // 设定深度缓存,[0,1]
	//	  DWORD Stencil                // 模板缓存所要设定的值
	//);

	device->BeginScene();
	
	//绘制之前的准备工作
	device->SetStreamSource(0, VB, 0, sizeof(vertex));      //指定数据流输入源
	device->SetFVF(vertex::FVF);                            //设置顶点格式
	device->SetIndices(IB);                                 //设置索引缓存(任意时刻只允许使用一个索引缓存)

	device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);   //绘制三角形
	//HRESULT DrawIndexedPrimitive(
	//	  D3DPRIMITIVETYPE Type,     //所要绘制的图元类型
	//	  INT BaseVertexIndex,       //起始顶点索引
	//	  UINT MinIndex,             //最小索引(相对于起始顶点索引)
	//	  UINT NumVertices,          //使用的顶点数量
	//	  UINT StartIndex,           //索引缓存中的起始索引
	//	  UINT PrimitiveCount        //所要绘制的图元数量
	//);

	device->EndScene();

	// 提交后台缓存(表面交换)
	device->Present(NULL, NULL, NULL, NULL);

	return true;
}

//窗口过程函数
LRESULT CALLBACK d3d::Wnd_Proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	case WM_KEYDOWN:
		//按下esc退出
		if (wParam == VK_ESCAPE)
			DestroyWindow(hwnd);
		break;
	}

	return DefWindowProc(hwnd, msg, wParam, lParam);
}

//WinMain
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
{
	if (!d3d::InitD3D(inst, 640, 480, true, D3DDEVTYPE_HAL, &device))
	{
		MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
		return 0;
	}

	if (!setup())
	{
		MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
		return 0;
	}

	d3d::EnterMsgLoop(display);

	cleanup();
	device->Release();

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值