DXUT框架剖析(1)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重!
原创作者: lovedday
原文出处:DXUT框架剖析(1)
DXUT(也称sample framework)是建立在Direct3D API之上的Direct3D应用程序框架,有了DXUT这样一个Direct3D程序框架,只需在这个框架的基础上编写相应的代码,从而简化了windows和Direct3D API的使用,可以高效地进行Direct3D程序设计。
生成一个Direct3D程序框架
第一步,运行Direct3D示例程序浏览器:
第二步,单击"EmptyProject"中的"Installl Project"安装工程:
第三步,在弹出的对话框中输入新工程的名称,修改该工程的创建路径,单击Install即可创建工程:
第四步,系统将自动完成工程的创建,然后弹出对话框询问是否查看创建的工程文件夹中的内容:
若选择是,则可以查看新创建的工程文件夹的内容:
使用Direct3D程序框架
通过上面的操作,Direct3D已经为我们创建好了一个应用程序框架,该框架主要包括以下文件:
其中最主要的两个文件是DXUT.h和DXUT.cpp。
除了上面这些通用文件外,Direct3D还生成了一个主程序文件,该文件的名字和工程名字相同,在此即是AppFrame.cpp。该文件主要由以下几个回调函数构成:
bool CALLBACK IsD3D9DeviceAcceptable(D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext);
bool CALLBACK ModifyDeviceSettings(DXUTDeviceSettings* pDeviceSettings, void* pUserContext);
HRESULT CALLBACK OnD3D9CreateDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext);
HRESULT CALLBACK OnD3D9ResetDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext);
void CALLBACK OnFrameMove(double fTime, float fElapsedTime, void* pUserContext);
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext );
void CALLBACK OnD3D9LostDevice( void* pUserContext );
void CALLBACK OnD3D9DestroyDevice( void* pUserContext );
函数名前使用"CALLBACK"表示声明的是一个回调函数,也就是说,这是DXUT框架为我们设置好的接口,DXUT框架将在合适的时机调用相应的回调函数。现在我们需要做的就是在这些回调函数中填写相应的代码完成所需要的功能。为了使DXUT框架能够调用这些回调函数,还需要在WinMain函数中为DXUT框架设置这些回调函数,代码如下:
// Set the callback functions DXUTSetCallbackD3D9DeviceAcceptable(IsD3D9DeviceAcceptable); DXUTSetCallbackD3D9DeviceCreated(OnD3D9CreateDevice); DXUTSetCallbackD3D9DeviceReset(OnD3D9ResetDevice); DXUTSetCallbackD3D9FrameRender(OnD3D9FrameRender); DXUTSetCallbackD3D9DeviceLost(OnD3D9LostDevice); DXUTSetCallbackD3D9DeviceDestroyed(OnD3D9DestroyDevice); DXUTSetCallbackDeviceChanging(ModifyDeviceSettings); DXUTSetCallbackMsgProc(MsgProc); DXUTSetCallbackFrameMove(OnFrameMove);
DXUT框架程序的整个“生命周期”可划分为三个阶段:启动、运行和结束。
第一阶段:启动
DXUT框架依次执行IsD3D9DeviceAcceptable()、ModifyDeviceSettings()、OnD3D9CreateDevice()、OnD3D9ResetDevice()这4个函数。
在创建某个Direct3D渲染设备之前,如果需要对渲染设备的特征进行检查,查看设备是否支持需要的功能,可将检查代码写在函数IsD3D9DeviceAcceptable()中。
在某个渲染设备创建之前,如果需要修改该渲染设备的设置,可将代码写在函数ModifyDeviceSettings()中。DXUT框架接下来就根据设置(或者是默认设置)创建最适合当前硬件的Direct3D渲染设备。例如,当硬件不支持某些功能时,可以通过使用参考设备进行模拟,设置使用参考设备代码通常写在该函数中。
DXUT框架创建了Direct3D设备之后,接下来会调用OnD3D9CreateDevice()回调函数,可在OnD3D9CreateDevice()回调函数中创建所有内存池类型为D3DPOOL_MANAGED或D3DPOOL_SYSTEMMEM的资源。以类型D3DPOOL_MANAGED创建的设备由Direct3D系统代替管理(位于显存或系统内存中),以类型D3DPOOL_SYSTEMMEM创建的设备位于系统内存中,在程序退出之前,这些资源常驻内存,不会出现设备丢失的现象。也就是说,以这两种内存类型创建的资源不需要程序员进行管理。
DXUT框架在调用OnD3D9CreateDevice()回调函数之后,将调用OnD3D9ResetDevice()回调函数。我们可在函数OnD3D9ResetDevice()中创建所有内存池类型为D3DPOOL_DEFAULT的资源,这一类资源将尽可能存放在显存中,这样可以提高程序的运行速度。但是,这类资源在程序运行时会出现设备丢失的现象,因此需要程序员自己管理。在设备丢失时释放它的内存,当设备恢复时重新为它分配内存。此外,观察变换矩阵和投影变换矩阵以及在整个程序运行期间保持不变的渲染状态通常也在该回调函数中设置。
如果性能不是很重要,使用D3DPOOL_MANAGED内存类型资源永远是一种安全的选择。
第二阶段:运行
DXUT框架调用回调函数MsgProc()处理各类消息,并在空闲时间反复调用OnFrameMove()和OnFrameRender()两个函数进行场景渲染。
在每一帧中,程序为实现对场景的刷新,为用户输入的响应而编写的代码通常写在函数OnFrameMove()中,例如设置世界变换矩阵实现物体的运动,它相当于“update”的性质,真正进行渲染的代码写在函数OnFrameRender()中。
需要说明的是,在应用程序运行期间,当Direct3D设备变为丢失状态时,DXUT框架会调用OnD3D9LostDevice()函数,释放所有在回调函数OnD3D9ResetDevice()中创建的设备资源。也就是说,这时释放的资源都是D3DPOOL_DEFAULT类型的。当Direct3D设备从丢失状态恢复时,DXUT框架会调用回调函数OnD3D9ResetDevice()重新创建所有类型为D3DPOOL_DEFAULT的资源。也就是说,在程序运行时,如果出现设备丢失现象,OnD3D9LostDevice()和OnD3D9ResetDevice()这一对函数就需要分别调用一次。
第三阶段:退出
在退出程序时,DXUT框架会依次调用OnD3D9LostDevice()和OnD3D9DestroyDevice()回调函数,在函数OnD3D9LostDevice()中释放由函数OnD3D9ResetDevice()创建的资源,在函数OnD3D9DestroyDevice()中释放由函数OnD3D9CreateDevice()创建的资源。
AppFrame.cpp的全部代码如下:
#include "resource.h"
//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false.
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable(D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
bool bWindowed, void* pUserContext)
{
// Typically want to skip back buffer formats that don't support alpha blending
IDirect3D9* pD3D = DXUTGetD3D9Object();
/*
HRESULT CheckDeviceFormat(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT AdapterFormat,
DWORD Usage,
D3DRESOURCETYPE RType,
D3DFORMAT CheckFormat
);
/*/
if(FAILED(pD3D->CheckDeviceFormat(pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat,
D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat)))
{
return false;
}
return true;
}
//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed.
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings(DXUTDeviceSettings* pDeviceSettings, void* pUserContext)
{
return true;
}
//--------------------------------------------------------------------------------------
// Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED)
// and aren't tied to the back buffer size.
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9CreateDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext)
{
return S_OK;
}
//--------------------------------------------------------------------------------------
// Create any D3D9 resources that won't live through a device reset (D3DPOOL_DEFAULT)
// or that are tied to the back buffer size.
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9ResetDevice(IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext)
{
return S_OK;
}
//--------------------------------------------------------------------------------------
// Handle updates to the scene. This is called regardless of which D3D API is used.
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove(double fTime, float fElapsedTime, void* pUserContext)
{
}
//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
HRESULT hr;
// Clear the render target and the zbuffer
V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 5, 5, 5), 1.0f, 0) );
// Render the scene
if( SUCCEEDED( pd3dDevice->BeginScene() ) )
{
V( pd3dDevice->EndScene() );
}
}
//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
bool* pbNoFurtherProcessing, void* pUserContext )
{
return 0;
}
//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9ResetDevice callback
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9LostDevice( void* pUserContext )
{
}
//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9CreateDevice callback
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
{
}
//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int )
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
// Set the callback functions
DXUTSetCallbackD3D9DeviceAcceptable(IsD3D9DeviceAcceptable);
DXUTSetCallbackD3D9DeviceCreated(OnD3D9CreateDevice);
DXUTSetCallbackD3D9DeviceReset(OnD3D9ResetDevice);
DXUTSetCallbackD3D9FrameRender(OnD3D9FrameRender);
DXUTSetCallbackD3D9DeviceLost(OnD3D9LostDevice);
DXUTSetCallbackD3D9DeviceDestroyed(OnD3D9DestroyDevice);
DXUTSetCallbackDeviceChanging(ModifyDeviceSettings);
DXUTSetCallbackMsgProc(MsgProc);
DXUTSetCallbackFrameMove(OnFrameMove);
// TODO: Perform any application-level initialization here
// Initialize DXUT and create the desired Win32 window and Direct3D device for the application
DXUTInit( true, true ); // Parse the command line and show msgboxes
DXUTSetHotkeyHandling( true, true, true ); // handle the default hotkeys
DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
DXUTCreateWindow( L"AppFrame Sample" );
DXUTCreateDevice( true, 640, 480 );
// Start the render loop
DXUTMainLoop();
// TODO: Perform any application-level cleanup here
return DXUTGetExitCode();
}
运行效果图:
下载示例工程
DXUT框架剖析(1)相关推荐
- DXUT框架剖析系列文章(原创:天行健 君子当自强而不息)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原创博客:天行健 君子当自强而不息 原文出处:DXUT框架剖析 DXUT框架剖析 ...
- DXUT框架剖析(14)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(14) 控件是用户接口的重要组成部分,为了便于用户操 ...
- DXUT框架剖析(13)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(13) 添加文本 DXUT框架对文本绘制进行了封装, ...
- DXUT框架剖析(11)
本文版权归博客园 原创作者: 原文出处:DXUT框架剖析(11) DXUT统计函数 函数 描述 DXUTGetFPS 获取当前每秒提交的帧数 DXUTGetFrameStats 获取一个指向字符串的 ...
- DXUT框架剖析(10)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(10) 管理DXUT框架的函数 函数 描述 DXUT ...
- DXUT框架剖析(9)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(9) 下面列出允许改变DXUT行为和获取内部变量的函 ...
- DXUT框架剖析(8)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(8) DXUT框架与错误处理 Direct3D AP ...
- DXUT框架剖析(7)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(7) (2)帧事件 框架也提供了帧事件,它在渲染过程 ...
- DXUT框架剖析(6)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(6) 在窗口和设备创建好之后,应用程序需要使用消息循 ...
- DXUT框架剖析(5)
本文版权归博客园 lovedday 所有,转载请详细标明原创作者及原文出处,以示尊重! 原创作者: lovedday 原文出处:DXUT框架剖析(5) 修改可用的设备 应用程序可以通过DXUTSet ...
最新文章
- golang 字符串拼接方式
- 从责任界定和问题预警角度 解读全栈溯源对DevOps的价值
- 如何用java语言调用tensorflow训练好的模型
- 播客#50:Sacha Greif
- [水力建模]EPANET代码解读1
- 云服务器磁盘挂载_云服务器快照是备份的吗?
- python---基础知识回顾(十)进程和线程(协程gevent:线程在I/O请求上的优化)...
- iis出现HTTP 错误 403.14 - Forbidden Web问题
- matlab 加随机数,随机数加上100:Matlab
- Java面试之项目介绍
- 时间序列预测在R中的应用 (Part1 简介和预测工具集)
- GTD工具 Wunderlist使用心得总结
- 抖音超级恶心的滑稽HTML源码
- Python -- 关于函数的学习(五) — 传递任意数量的实参
- c语言float m1 m2什么意思,M0、M1、M2的涵义及其作用
- python与传感器交互_Python-socket实现与小米传感器通信
- docker安装步骤
- python为什么用号做注释符_Python 为什么用 # 号作注释符?
- 【毕业设计】答 辩 技 巧 二(以一个过来人的身份,祝各位答辩 过 过 过)
- Image Processing Algorithms
热门文章
- Vue脚手架中添加favicon.ico图标失效问题
- Use // eslint-disable-next-line to ignore the next line.解决办法
- Opencv之以亚像素精度获取图片的ROI--cv.getRectSubPix
- 动态规划算法经典例题_c动态规划精简例题
- 漫游飞行_除了防打扰,手机飞行模式还有这些作用
- windows分辨率修改工具_3个修改图片DPI的方法
- 一个近乎完美基于Dubbo的微服务改造实践
- 关于如何提高代码可测试性的一些看法
- 和菜鸟一起学linux之V4L2摄像头应用流程【转】
- 关于异常的合理处理方式