(注:【D3D11游戏编程】学习笔记系列由CSDN作者BonChoix所写,转载请注明出处:http://blog.csdn.net/BonChoix,谢谢~)
从上次绘制一个简单立方体的例子中,我们可以发现,即使是一个十分简单的程序,其代码长度也是相当的长。但实际上,大多数代码只是用于了Win32、D3D11的初始化,剩下的才是我们真正关心的绘制代码。一方面,这些代码妨碍我们直接关注核心部分, 另一方面,为了避免在后面每次创建新的程序时生硬地复制、粘贴这些初始化代码,我们这次创建一个简单的程序框架。这个框架通过面向对象的方式把Win32、D3D11初始化、Windows消息处理等这些固定代码封装了起来,以后可以重复利用它们。 这样在创建新的程序时,直接导入该框架,并编写核心程序即可。
1. 框架简介
刚开始时,我们的框架功能十分简单。在后面深入学习D3D11时,我们会不断往该框架中添加新的功能,使它逐渐地丰满起来。
新的框架主要包括如下内容:
1.1 主程序
这部分是该框架的核心部分,用于封闭Win32和D3D11中的固定代码,即初始化、消息处理等。类名为:WinApp,其定义如下:
class WinApp
{
public:
WinApp(HINSTANCE hInst, std::wstring title = L"D3D11学习程序框架", int width = 640, int height = 480);
~WinApp();
//基本内联成员函数
HINSTANCE AppInstance() const { return m_hInstance; }
HWND Window() const { return m_hWnd; }
int Width() const { return m_clientWidth; }
int Height() const { return m_clientHeight; }
void SetWindowTitle(std::wstring title) { SetWindowText(m_hWnd,title.c_str()); }
/*
在子类中重写这些函数以实现自定义的功能
对于个别函数,在重写时,要先调用父类的函数,再添加自定义的功能,
比如:Init(),在子类Init()中,需要先调用WinApp::Init()。
同样也适合于OnResize()。
*/
virtual bool Init(); //程序初始化
virtual bool OnResize(); //当窗口大小改变时调用
virtual bool Update(float timeDelt) = 0; //每帧更新
virtual bool Render() = 0; //渲染
virtual LRESULT CALLBACK WinProc(HWND,UINT,WPARAM,LPARAM);
int Run(); //主循环
protected:
bool InitWindow(); //初始化Win32窗口
bool InitD3D(); //初始化D3D11
void CalculateFPS(); //计算帧率
protected:
HINSTANCE m_hInstance; //应用程序实例句柄
HWND m_hWnd; //窗口句柄
int m_clientWidth; //窗口大小
int m_clientHeight;
bool m_isMinimized; //是否最小化
bool m_isMaximized; //是否最大化
bool m_isPaused; //是否暂停运行
bool m_isResizing; //当鼠标正在改变窗口尺寸时
ID3D11Device *m_d3dDevice; //D3D11设备
ID3D11DeviceContext *m_deviceContext; //设备上下文
IDXGISwapChain *m_swapChain; //交换链
ID3D11Texture2D *m_depthStencilBuffer; //深度/模板缓冲区
ID3D11RenderTargetView *m_renderTargetView; //渲染对象视图
ID3D11DepthStencilView *m_depthStencilView; //深度/模板视图
std::wstring m_winTitle; //窗口名称
Timer m_timer; //应用程序定时器
private:
//避免复制
WinApp(const WinApp&);
WinApp& operator = (const WinApp&);
};
在该类中,主要包括三类的成员函数,一部分为基本函数,即“非virtual”函数,这些函数功能是固定的,子类直接继承它们并使用之,不需要重新定义;另一部分即所有的”非纯virtual“函数,这些函数在框架中实现基本功能,允许在子类中重写,以添加所需的功能,比如初始化;第三部分即”纯virtual“函数,这些函数在框架中未定义,在定义子类时必须重写之,这类函数主要为更新、渲染相关函数。
由上面代码可以看出,该框架主要封装了程序窗口大小、句柄、窗口相关状态(最小化、最大化、暂停/运行等),以及D3D11相关的基本核心变量,此外还包括一个定时器,用于控制程序的帧率及速度。这些成员变量全部为protected类型,以允许在子类中直接进行使用。
关于消息处理函数,该框架实现了大多数常用功能,位于WinProc该成员函数中,因此在一般情况下不需要重写消息处理函数。此外要注意,类中的成员函数是不能直接用于Windows消息处理函数的!因此我们在该框架中使用了一点小技巧,在Windows消息处理函数中,通过一个全局的程序对象来调用该成员函数,且使用完全一样的参数。这样就把间接地把消息处理函数转换到成员函数中了。详细情况请参考本文附加的源代码。
1.2 定时器
这个定时器即在前几篇文章中我们实现的定时器,在该框架中我们直接把它加了进来。关于定时器的设计,请参考定时器的实现。
1.3 辅助函数
框架中的辅助函数定义位于头文件"AppUtil.h"中,定义位于相应的cpp文件。这个文件也会随着学习的深入添加新的功能,暂时仅仅包括如下功能:安全地释放D3D11接口(SafeRelease函数),常见的颜色值的定义。
2. 框架导入
该框架中的所有文件位于Common文件夹当中,该文件夹可以放置在任意的目录中,但有以下要求:1. Common文件夹的目录要添加到IDE的Include目录下,以在程序中能够正确地include框架中的文件;2. 在每个新建项目中,在左边SolutionExplorer中添加一个新的目录(比如取名为Common),把框架中所有文件导入。如下图所示:
关于如何配置IDE的include目录及在solutionExplorer中添加新的目录,请参考准备工作中有关配置Visual Studio环境变量部分。此外,默认情况下,我把Common目录放在了项目所在目录下,并且把该目录添加到了include目录中。因此本文末尾的附加代码中的.sln文件直接导入就可以了。如果移动了Common目录,则需要再配置include目录。
3. 利用框架创建新的应用程序
下面是每次在该框架基础上创建新的应用程序的步骤。
3.1 创建一个新类,并继承主框架类:WinApp
每一个新的应用程序都要有一个相应的子类,继承WinApp,同时重写Update和Render两个函数。其他virtual函数按需进行重写。如下一个例子:
class Basic: public WinApp
{
public:
Basic(HINSTANCE hInst, std::wstring title = L"D3D11学习程序框架", int width = 640, int height = 480):
WinApp(hInst,title,width,height)
{}
bool Update(float delta);
bool Render();
private:
};
3.2 在新类中添加程序中所需的所有成员变量及成员函数
框架中提供了程序最基本的成员函数与成员变量,针对各个应用程序的需求,在子类中添加相应的新的成员。比如用于更新effect文件中的全局变量的相关接口、顶点缓冲区与索引缓冲区、纹理接口等,以及用于初始化的相关成员函数等。该步骤由具体程序而定。对于一个最简单的不绘制任何图形的例子,只要重新定义Update和Render函数即可。如下所示:
bool Basic::Update(float delta)
{
return true;
}
bool Basic::Render()
{
m_deviceContext->ClearDepthStencilView(m_depthStencilView,D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL,1.f,0);
m_deviceContext->ClearRenderTargetView(m_renderTargetView,reinterpret_cast<const float*>(&Colors::Silver));
m_swapChain->Present(0,0);
return true;
}
3.3 添加WinMain函数
最后一步即添加程序入口函数,创建应用程序对象并执行。如下所示:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
{
Basic app(hInstance);
if(!app.Init())
return -1;
return app.Run();
}
使用该框架的全部过程就是这些,下面是相关源代码:
4. 源代码
程序框架源代码
分享到:
相关推荐
一个用于学习D3D11的程序框架,最开始的部分。随着学习深入逐渐完善、添加高级功能。
经典d3d11游戏编程入门,作者Allen Sherrod和Wendy Jones,中英文高清pdf附加随书源码
D3D11游戏编程,XNAMath介绍,XMMATRIX部分示例代码
【D3D11游戏编程】中XNAMath介绍,XMVECTOR部分示例代码。
【C++】D3D11 最新HOOK 源码支持X86_X64 【C++】D3D11 最新HOOK 源码支持X86_X64 【C++】D3D11 最新HOOK 源码支持X86_X64 【C++】D3D11 最新HOOK 源码支持X86_X64 【C++】D3D11 最新HOOK 源码支持X86_X64 【C++】D3...
在Qt5窗口显示D3D11的程序示例,运行前需要自己设置D3D11的环境和Qt5的环境。
该资源包含一个D3D11程序框架,示例程序实现了一个光照计算模型。
https://blog.csdn.net/zlyadvocate/article/details/118669454配套代码
2、D3D11利用D3D9传入的HANDLE使用OpenSharedResource来打开句柄实现D3D9到D3D11的数据传递 需要的库 1、NVAPI 安装完成后需要运行NVIDIA Capture SDK\bin目录下的NvFBCEnable.exe使能NVFBC抓屏 2、DXSDK_Jun10 坑...
一个演示使用D3D11实现透明效果的示例程序,包括主程序和一个程序框架,附带可执行程序。如有问题,欢迎交流~
ffmpeg硬解码。windows下支持d3d9 d3d11硬件加速
对ID3D11Texture2D实现颜色填充(对D3D11实现IDirect3DDevice9::ColorFill效果) 运行环境VS2019 编Rlease x86版本
windows mft d3d11渲染显示 播放器 键盘D删除播放器 键盘P 重新创建和播放视频
该文件包含所示源代码(包括一个d3d11程序框架),及可执行程序。如果exe程序无法执行,请自行手动编译。 相关操作: 要通过'1','2','3','4'数字键来打开、关闭雾效等一些功能。 鼠标左键按下旋转镜头,右键按下调整...
d3d11中通过cube mapping实现天空盒效果。包含全部源代码及可执行程序。 操作方法:通过鼠标左键旋转镜头。
D3D11_Render
D3D11初始化,一个最简单的D3D11应用程序。学习D3D的开始。
D3D11_ShadowMap
D3D11_Blur
D3D11_fire