DX11 游戏开发笔记 (三) DX11 实现类框架 (下)

最近心情有点波动,导致博客写的一塌糊涂,上篇博文草草就结束了,很对不起自己,整理好心情,准备好好写下博文,算是对自己的考验吧。

C++是一门很厉害的语言,在游戏这方面更是显得非常出色,C++最基础的东西就是类,怎么将写好的流程代码封装是一个技术活,推荐《effective c++》这系列的三本书,(当然其中有些约定不适合游戏)它或许无法提升一个游戏可玩性,甚至它还会增加你游戏负担,但会让你如鱼得水般编写出代码,并且代码可读性还不错,维护也方便,如果你按照书本上的建议做了的话,相信我,当你客户要求改变时,你会感激你自己的。

笔者每次编写程序时,一般都要拿起床头的工具书《代码大全2》,询问自己代码是否符合规定,游戏引擎是个高端技术活,底层代码编写越规范越方便整合、调试。

 

场景begin:

 

(1) 摄像机class

(2)d3dclass (DX11class)

(3)图形class

(4)着色器class

(5)DX的底层按键输入class

(6)系统class

 

图形class   =摄像机class   +   DX11class  +  着色器class

系统class =图形class  +    DX的底层按键输入class

 

 

老鸟:小白,上次让你封装DX11基础框架的作业完成了吗?

小白:嗯,可花了我不少时间,当然物有所值,我受益良多。

老鸟:哦,说来听听。

小白:单纯的将数据和行为封装并不难,只是简单的复制粘贴,把数据改为类私有,写好构造和析构,注意一下变量名和函数名,函数就是简单把行为分类。

老鸟:嗯恩。

小白:难的是类之间交互的数据,例如shaderclass需要一个矩阵:世界X取景X投影,其中世界矩阵和投影矩阵属于d3dclass,取景矩阵属于camerclass,所以我需要在graphicsclass里去处理这个流程,我给d3dclass和cameraclass增加“接口”函数,把世界矩阵、取景矩阵、投影矩阵暴露出来(传引用)。

BOOL  graphicsclass::Frame_Graphics()
{

	camera_class->Frame_Camera();

	XMMATRIX WorldMatrix, ViewMatrix, ProjMatrix;

	d3d_class->GetWorldMatrix(WorldMatrix);
	d3d_class->GetProjectionMatrix(ProjMatrix);
	camera_class->Get_ViewMatrix(ViewMatrix);

	shader_class->SetMartix(WorldMatrix, ViewMatrix, ProjMatrix);

	
}

小白:后来我又遇到一个难题,shaderclass跟d3dclass在渲染部分高度耦合在一起:

void    Render_D3D(float red, float green, float blue, float alpha)
{

	float color[4];


	// Setup the color to clear the buffer to.
	color[0] = red;
	color[1] = green;
	color[2] = blue;
	color[3] = alpha;

	// Clear the back buffer.
	g_deviceContext->ClearRenderTargetView(g_renderTargetView, color);
	// Clear the depth buffer.
	g_deviceContext->ClearDepthStencilView(g_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

	//全部的场景绘制工作在这里面进行.....
	//指定输入布局(Input Layout)
	g_deviceContext->IASetInputLayout(g_inputLayout);
	//指定顶点缓存
	UINT stride = sizeof(Vertex);
	UINT offset = 0;
	g_deviceContext->IASetVertexBuffers(0, 1, &g_VB, &stride, &offset);

	//指定图元拓扑类型
	g_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	//从Technique获取全部pass并逐个渲染
	ID3DX11EffectTechnique *tech = g_effect->GetTechniqueByName("BasicDraw");
	D3DX11_TECHNIQUE_DESC techDesc;
	tech->GetDesc(&techDesc);
	for (UINT i = 0; i < techDesc.Passes; ++i)
	{
		tech->GetPassByIndex(i)->Apply(0, g_deviceContext);
		g_deviceContext->Draw(3, 0);
	}

	g_swapChain->Present(0, 0);

	return;

}

小白:我一开始对其完全没有办法,因为d3dclass的渲染被shaderclass的参数从中横插一脚,难不成我把shaderclass中影响到d3dclass的参数全部设置接口,然后在传参使用,而后我发现需要传的参数太多,暴露太多数据会导致shaderclass封装性遭到破坏,然后我参考了一下DX11龙书的代码,恍然大悟,把d3dclass的Render_D3D分成两部分:BeginScreen_D3D、EndScreen_D3D,把渲染的部分放入shaderclass类中,这样只需获得d3dclass中的g_deviceContext传出来即可。

BOOL  graphicsclass::Frame_Graphics()
{


	d3d_class->BeginScreen_D3D(color[0], color[1], color[2], color[3]);

	shader_class->SetMartix(WorldMatrix, ViewMatrix, ProjMatrix);

	if (!shader_class->Render(d3d_class->GetDeviceContext(), 3))
		return FALSE;

	d3d_class->EndScreen_D3D();

	return TRUE;
}

小白:后来我在编写systemclass时,通过input_class获取按键状态去改变camera_class的变量时,突然发现cameraclass已经被我封装进graphicsclass中,如果传参调用要通过两次抽象层,显然是不行的,故我在graphicsclass中加了一个函数:

cameraclass*  graphicsclass::Icamera()
{
	return camera_class;
}

小白:这样简单调用就好了,

cameraclass*  camera = graphics_class->Icamera();

小白:但我发现这样忠实的把camera的所有函数的暴露出来了,可是我也一时找不到好的办法,只不过用户不会这样操作的。

老鸟:嗯恩,用户的确不会这样操作,但是测试会,不是有句话叫:开发最大的敌人就是测试。

老鸟:其实这样的情况很常见,大致分为两种情况:一种只要数据,另一种就如上述需要行为;只需要数据,且数据重合度高,那就提取出来为结构体,只需要行为就提取出来写成基类虚函数,但本例提取出来成为基类,只是单纯的一对一,显然意义不大,读者若有意实现,想必是极好的,那样请务必在留言中贴出来,谢谢。(在某些工程项目中,会有这样的事,我们只是写一个简单项目,然后有一个复杂完善的模板,这时我们往往会封装模板,并只提供我们简单项目的接口,嗯恩对,我们又在”愚弄“客户了)

 

小白:这是我改装后的版本:https://pan.baidu.com/s/1S_kDOudK_-z4MAEzqhTyoQ

 

老鸟:小白,有这样一句话,好的程序应如良品佳文,能人人娓娓道来,你能道一道你的辛苦成果吗。

 

小白:这有何难:正所谓佳人倾城,难睹芳颜,佳人提出这样的要求:想一见芳容,需入WinMain大门,过一过system这道,这system有三步:一难为window创建,二难为input控制,三难为graphics艺术,一难接一难,一难胜一难。这第三难尤为其盛,一大难分三小难:d3d(判断你的图形基础)、camera(认定你看艺术的角度)、shader(实战你的绘图技术)。当通过system此道,便能见到属于你自己的佳人。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值