DX学习笔记(初始化Direct 3D)

首先是头文件,在那里面定义了3个函数,分别是初始化函数InitD3D(),消息循环函数EnterMsgLoop ,窗口过程函数WndProc()

其余的Release() Delete()都是以模板函数定义。

Release()为了方便释放接口,并设置为NULL,而Delete()则是为了方便删除,并清空指针。

注释很多(毕竟本弱是Win32的新手,很多概念都得靠网上百度才能理解)

d3dUtility.h

#ifndef __d3dUtilityH__
#define __d3dUtilityH__

#include<d3dx9.h>
#include <string>

namespace d3d
{
	bool InitD3D(
		HINSTANCE hInstance, //当前应用程序实例的句柄
		int width, int height, //后台缓存的表面宽度和高度
		bool windowed, //是否窗口化 
		D3DDEVTYPE deviceType, //D3D设备类型  硬件(HAL)或者引用(REF)或软件(SW)
		IDirect3DDevice9** device);//以创建的设备(用于输出)

	int EnterMsgLoop(
		bool(*ptr_display)(float timeDelta));

	LRESULT CALLBACK WndProc(
		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 // __d3dUtilityH__

d3dUtility.cpp

分了四个步骤去实现D3D的初始化。

步骤1:创建 IDirect3D9 对象
步骤2:校验硬件顶点计算
步骤3:填充D3DPRESENT_PARAMETERS 结构的初始值
步骤 4:创建设备(除此以外还实现了该程序的消息循环,EnterMsgLoop(其余注释的补充了很多我就不多说了)

#include "d3dUtility.h"

bool d3d::InitD3D(HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9 **device)
{
	WNDCLASS wc;

	wc.style			= CS_HREDRAW | CS_VREDRAW;//窗口类型(当水平长度,垂直长度,或者位置改变,重画整个窗口)
	wc.lpfnWndProc		= (WNDPROC)d3d::WndProc;//窗口处理函数
	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() - FALIED", 0, 0);
		/**
		MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
		hWnd : 消息框拥有的窗口
		lpText :消息框的内容
		lpCaption :消息框的标题
		uType :指定标志中的一个来显示消息框的按钮以及图标(默认,只有一个确认按钮)
		**/
		return false;
	}
	
	HWND hwnd = 0;
	hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App",
		WS_EX_TOPMOST,//设置窗口风格,将窗口设为置顶
		0,0,width,height,
		0/*父窗口*/, 0/*菜单*/, hInstance,0/*扩展*/);
	if (!hwnd)
	{
		::MessageBox(0, "CreateWindow() - FALIED", 0, 0);
		return false;
	}

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

	HRESULT hr = 0;

	//步骤1:创建 IDirect3D9 对象
	IDirect3D9 *d3d9 = 0;
	d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

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

	//步骤2:校验硬件顶点计算

	D3DCAPS9 caps;
	d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
	//caps会返回装载着当前显卡设备能力的信息

	int vp = 0;
	if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

	//步骤3:填充D3DPRESENT_PARAMETERS 结构的初始值

	D3DPRESENT_PARAMETERS d3dpp;
	d3dpp.BackBufferWidth = width;
	d3dpp.BackBufferHeight = height;
	d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
	d3dpp.BackBufferCount = 1;
	d3dpp.MultiSampleQuality = 0;
	d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow = hwnd;
	d3dpp.Windowed = windowed;
	d3dpp.EnableAutoDepthStencil = true;//若设置为true,则D3D自动创建并维护深度缓存或模板缓存
	d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;//D24S8用24位表示深度并将8位保留供模板使用
	d3dpp.Flags = 0;
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;//刷新频率设为默认值
	d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;//当交换链中后台缓存切换到前台缓的时候最大速率设为立即提交

	
	//步骤 4:创建设备
	hr = d3d9->CreateDevice(
		D3DADAPTER_DEFAULT,//主适配器
		deviceType, 
		hwnd,
		vp,
		&d3dpp,
		device);		   //返回创建的设备

	if (FAILED(hr))
	{

		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();
			float timeDelta = (currTime - lastTime)*0.001f;

			ptr_display(timeDelta);

			lastTime = currTime;
		}
	}
	return msg.wParam;//来自一条表示退出的消息
}
	


d3dInit.cpp

这里主要是实现了Display()显示函数。主要的实现细节都在注释里补充,唯一需要强调的 - - 注意自己创建的是控制台还是win32应用程序。若是控制台,需要转化为win32应用程序

#include"d3dUtility.h"
IDirect3DDevice9* Device = 0;

bool Setup()
{
	return true;
}

void Cleanup()
{

}

bool Display(float timeDelta)
{
	if (Device)
	{
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
		/**
		Clear(DWORD Count,const D3DRECT *pRects,DWORD Flags , DWORD Color ,float Z , DWORD Stencil);
		Count	 pRect数组中矩形的数目
		pRect	 所要执行清除操作的屏幕矩形数组。该参数允许我们只对表面的部分区域进行清除操作。
	        Flags	 指定所要清除的表面.我们可清除下列表面中的一个或多个。
			D3DCLEAR_TARGET 绘制目标表面,通常指后台缓存
			D3DCLEAR_ZBUFFER 深度缓存
			D3DCLEAR_STRNCIL 模板缓存
		Color	 指定将绘制目标体设置为何种颜色
		Z		 深度缓存所要设定的值
		Stencil	 模板缓存所要设定的值
		**/
		Device->Present(0, 0, 0, 0);//提交后台缓存
	}
	return true;
}

LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
	case WM_KEYDOWN:
		if (wParam == VK_ESCAPE)
			::DestroyWindow(hwnd);
		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI  WinMain(HINSTANCE hinstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
	if (!d3d::InitD3D(hinstance, 640, 480, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, "InitD3D() - FAILED", 0, 0);
		return 0;
	}

	if (!Setup())
	{
		::MessageBox(0, "Setup() - FAILED", 0, 0);
		return 0;
	}

	d3d::EnterMsgLoop(Display);

	Cleanup();

	Device->Release();

	return 0;
}




  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值