龙书学习笔记——关于Direct3D中的初始化操作源码分析

 在《DirectX 12 3D 游戏开发实战》此书的第四章中详细介绍了基础的D3D的初始化操作该如何操作,具体的步骤如下:

1、创建DirectX3D设备

2、创建围栏(Fence)为了保证GPU和CPU的处理不发生不必要的冲突、扫描描述符的大小

3、检测用户设备是否支持多重采样4X MSAA

4、必须依次创建命令队列、命令列表分配器和命令列表(在完成对命令列表的输入后必须关闭对命令列表的输入操作才能将命令由分配器放入进命令队列中)

5、描述并创建交换链(backbuffer与frontbuffer之间的关系必须理清,在前台缓冲区中存的是当前的呈现在屏幕面前的像素

,而在后台缓冲区中存的是下一帧将呈现的你面前的像素信息,即提前画好,这样就不会有闪烁的现象出现——来不及画)

6、创建应用程序所需要的描述器堆(描述器堆用于存放程序中要用到的描述器/视图:RTV、DSV)

7、调整后台缓冲区的大小,并为它创建渲染目标视图

8、创建深度/模板缓冲区及与之相关的深度/模板视图

9、设置视口和裁剪矩形(显示设置)

 

以下是书中的源代码:其中需要借用到已经写好的d3dApp源代码以及DXColor的头文件,用颜色的头文件是因为代码中有要用到有关颜色的设置,即背景的设置。

#include"../../Common/d3dApp.h"
#include"DirectXColors.h"

using namespace DirectX;

class InitDirect3DApp:public D3DApp
{
public:
	InitDirect3DApp(HINSTANCE hInstance);
	~InitDirect3DApp();

	virtual bool Initialize()override;								// 编写初始化代码:分配资源、初始化对象、建立3D场景等

private:
	virtual void OnResize()override;								// 调整后台缓冲区和深度/模板缓冲区的尺寸
	virtual void Update(const GameTimer& gt)override;				// 在绘制每一帧时都会调用该抽象方法,可用它来更新3D应用程序(呈现动画、移动摄像机等等)
	virtual void Draw(const GameTimer& gt)override;					// 在绘制每一帧时都会调用该抽象方法
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,		// 为调试版本开启运行时的内存检测,方便监督内存泄漏的情况
	PSTR cmdLine, int showCmd)
{
	// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

	try
	{
		InitDirect3DApp theApp(hInstance);
		if (!theApp.Initialize())
			return 0;

		return theApp.Run();
	}
	catch (DxException& e)
	{
		MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
		return 0;
	}
}

InitDirect3DApp::InitDirect3DApp(HINSTANCE hInstance)				// 不做操作,默任D3DApp中的加载操作
	:D3DApp(hInstance)
{
}

InitDirect3DApp::~InitDirect3DApp()
{
}

bool InitDirect3DApp::Initialize()									// 检测基类中场景是否加载
{
	if (!D3DApp::Initialize())
		return false;

	return true;
}

void InitDirect3DApp::OnResize()
{
	D3DApp::OnResize();
}

void InitDirect3DApp::Update(const  GameTimer& gt)
{
}

void InitDirect3DApp::Draw(const GameTimer& gt)
{
	ThrowIfFailed(mDirectCmdListAlloc->Reset());								// 在确保完成GPU的操作后对命令列表分配器进行重置
																				// 重复使用记录命令的相关内存

	ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));		// 在通过ExecuteCommandList方法将某个命令列表加入命令
																				// 队列后,我们便可以重置该命令列表。以此来复用命令列表及其内存

	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(
		CurrentBackBuffer(),
		D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));		// 对资源的状态进行转换,将资源从呈现状态转换为渲染目标状态

	mCommandList->RSSetViewports(1, &mScreenViewport);							// 设置视口和裁剪矩形。它们需要随着命令列表的重置而重置
	mCommandList->RSSetScissorRects(1, &mScissorRect);							

	mCommandList->ClearRenderTargetView(
		CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr
	);																			// 清楚后台缓冲区和深度缓冲区
	mCommandList->ClearDepthStencilView(
		DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | 
		D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr
	);

	mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
																				// 指定将要渲染的缓冲区
	mCommandList->ResourceBarrier(
		1, &CD3DX12_RESOURCE_BARRIER::Transition(
			CurrentBackBuffer(),
			D3D12_RESOURCE_STATE_RENDER_TARGET,
			D3D12_RESOURCE_STATE_PRESENT
		));																		// 在对资源状态进行转换,将资源从渲染目标转换回呈现状态

	ThrowIfFailed(mCommandList->Close());										// 完成命令的记录

	ID3D12CommandList* cmdLists[] = { mCommandList.Get() };						// 将待执行的命令列表加入命令队列
	mCommandQueue->ExecuteCommandLists(_countof(cmdLists), cmdLists);

	ThrowIfFailed(mSwapChain->Present(0, 0));									// 交换后台缓冲区和前台缓冲区
	mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;

	FlushCommandQueue();														// 等待此帧的命令执行完毕。
}

本书为英文原版的中文翻本,不得不说书中的翻译十分详细,而且也有及其详细的注释(其中包含有作者自己的心得体会在内),建议对游戏引擎构建有兴趣的人购买学习。

以下更改相对于 E_D3D9 1.0正式版: 1:[!]"E_D3D9" 改名为“E_DirectX".为其他DirectX组件作准备. 2:[!]调用"d3dx9_42.dll"库改为"d3dx9_39.dll"库.直接影响相关的ID3DX...类. 3:[!]优化各类(修改为继承),删除与基类重复的方法,相对减少源码体积(不多,约20KB). 3:[+]ID3DXPMesh 之前版本漏掉了(MSDN内没有,d3dx9mesh.h有). 4 [+]ID3DXSPMesh 之前版本漏掉了(MSDN内没有,d3dx9mesh.h有). 5:[+]IDirect3D9Ex 6:[+]IDirect3DDevice9Ex 7:[+]IDirect3DSwapChain9Ex 8:[+]IDirect3D9ExOverlayExtension 9:[+]IDirect3DDevice9Video 10:[+]IDirect3DAuthenticatedChannel9 11:[+]IDirect3DCryptoSession9 12:[+]IDirectInput8 13:[+]IDirectInputDevice8 其DIDATAFORMAT参考了Delphi的JEDI后处理的.若有更好的方法欢迎讨论. 14:[+]IDirectInputEffect 15:[*]日后会陆续添加DirectX的其余组件,并且修复现有问题. (以后版本会整合发布,改动都将写入日志,公开免费发布,以谋求易语言完美调用原生DirectX所有组件方法. 待组件全了后,我会定期逐个类/方法测试,顺便写些Demo.) 提示: 有易友建议我使用EATL,我大致看了下原理是类似的.但它改写了易语言的类(也是其亮点),从而导致可以直接调用. 对于E_DirectX这个项目来讲,我个人感觉意义不是很大(该处理的类型还得处理!). 并不是说EATL不好,本人多重考虑后感觉不适合. 许多类方法可能存在问题 务必注意 特征/情况如下: 方法参数类型为文本型、字节集、所有类型的数组、以及自定义类型成员含有其他自定义类型的,这些未经处理的大多存在问题. 还有小数型参数与返回值的问题("Call"的问题),第一个版本(E_D3D9 Beta1)存在此重大问题.其后续的版本基本都已修复. 以上问题基本皆由易独特的类型存储结构无法与之匹配而引起的.(了解C++类型存储结构的小伙伴可以很快想到处理办法.) 模块还有大量问题没有处理,本人没有那么多时间和精力去逐个测试,除了自己用到的方法以外,许多都是简单处理下(工作量异常大! 无奈之举,以后慢慢修复吧.也可以自己参照我处理过的方法自行研究,开源也是有此目的.) 若发现问题可以发送相关的代码到我的邮箱. (此文最底下或模块的作者信息一栏),便于我整合进下一版本. 承诺: 以后所有版本皆会以免费开源形式发布,可任意使用,无任何限制.(据我所知之前也有不少因此受益的小伙伴,才让我更有信心继续下去.) 声明: E_DirectX(E_D3D9) 从诞生以来一直是以无偿开源的形式存在,同时因此作者(Roc/xc.roc)也无法对产品和用户进行有效的约束或限制, 同时也不承担因为该产品所带来的后果,若造成任何损失/后果由使用者自行承担.请大家谨慎考虑取舍! 总而言之,一切如涛哥所言:"向正确的方向前进!". 动态: 本人最近根据某易友的建议正在开发Essen GUI(游戏界面库),主要是应用于游戏环境(Hook D3D - -!). 会以开源模块的形式小范围收费发布,并且给予相关技术支持.有相关需求的用户也可以联系我邮箱. 以后会建立相关Q群供用户交流. 大致特点:简单、易用、可扩展性(你能想到的,你能见到的组件几乎都能扩展出来.类似Ex_DUI,但也所有区别.).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值