DirectX框架

 

所谓的框架是指SDK目录下\Samples\C++\Common路径下的DXUT系列函数包装。

                  DXSDK2006和2003版的比起来更新了不少东西,比如DirectX10,还有Managed
                  DirectX等等。不过我关心的还是D3D9。除了个别接口的更改之外,DXSDK2006还提供了一套图形控件的类库,它的界面还是很漂亮的:)


                  学习一个框架还是从它的入口学习比较方便,否则容易迷失在无穷无尽的API和层层包装之中。DXSDK2006的框架和2003版的DX9.0c框架有很大的不同。首先是2003版的框架中提供了一个CD3DApplication类,这个类对于初始化,清除,以及游戏窗口的创建,游戏主循环进行了包装。这是一个不错的类,不知道为什么在2006版中去掉了。不过不要紧,2006版的框架中提供的一些C包装函数已经足够了。在看这些函数之前,我们还是先来看看SDK目录下\Samples\C++
                  \Direct3D\Tutorials中有些什么吧。

                  //tutorials中的几个范例都是经典入门的基本例子,包括了创建设备,定点,矩阵,贴图、模型调用和hlsl,《3d游戏编程》一书把索引缓冲区的例子作为附加的新范例。


                  对D3D应用程序有了大概了解之后就可以看空框架程序了。这个程序可以在Samples\C++\Direct3D\EmptyProject中找到。


                  从WinMain中的调用可以看到,框架首先设定一堆回调函数,很多事情的是在用户自己写的回调函数中实现。从DXUTInit开始,程序开始调用框架内的API来完成初始化——创建窗口——创建设备——主消息循环——退出等一系列操作。调查Common目录下DXUT.cpp文件就可以发现DXUTInit函数干了以下几件事情

                  ①     设定开始调用这个函数的标志符
                  ②     InitCommonControls
                  ③     保存当前的sticky/toggle/filter键
                  ④     通过事先导入winmm.dll的方法timeBeginPeriod来确保调用Sleep的准确性
                  ⑤     设定一些标志附,读取命令行参数
                  ⑥     检查版本
                  ⑦    
                  获得D3D对象指针。值得一提的是框架中大部分全局变量是通过类DXUTState的静态变量state的get/set方法得到的。这些get/set方法是用宏定义的,里面调用了加锁和解锁,因此保证了全局变量设定的线程安全。这些全局性的变量包括D3D对象指针,D3D设备对象指针,BackBufferSurfaceDesc,DeviceCaps,窗口HINSTANCE,窗口句柄HWND,焦点句柄HWNDFocus,全屏设备句柄,窗口设备句柄,窗口客户端矩形,模式切换时窗口客户端矩形,模式切换时全屏客户端矩形,Time,ElapsedTime,FPS数,窗口标题,设备数据DeviceStats,以及是否暂停渲染,时间是否暂停,窗口是否激活等标志,一些窗口事件等等。这些都可以通过DXUTGETXXX/DXUTSETXXX/DXUTISXXX系列包装函数获得。

                  ⑧    
                  通过DXUT_Dynamic_Direct3DCreate9创建D3D对象。很多D3D底层API都是通过动态的方式加载的,这样有利于效率的提高。

                  ⑨     重设全局时钟
                  ⑩    
                  设定DXUTInited为true。很多DXUT系列的函数都喜欢在入口设定一个开始调这个函数的标志,在出口设定一个这个函数已经被调过的标志,这样可以在以后再次调用这个函数的时候了解当前什么工作已经做了,什么工作没做需要补做。我想这个主要是用来防止函数重入问题的吧。其他函数中的这一对函数就不再提了

                   呼~第一个函数大致看完了,接下来是DXUTCreateWindow函数。什么?要问DXUTSetCursorSettings为什么被无视?因为这个函数不重要。DXUTCreateWindow的工作大致是这样的

                  ①     判断关于设备的CallBack有没有设定好
                  ②     判断DXUTInit()有没有被调用成功(注意不是有没有调用)。
                  ③     获得焦点句柄,因为窗口还没有创建,所以这个句柄应该是NULL
                  ④     设定HInstance
                  ⑤     设定窗口类
                  ⑥     注册窗口类
                  ⑦     设定窗口位置和大小。好长一段代码,汗
                  ⑧     创建窗口。终于。。。
                  ⑨     设定窗口焦点句柄,全屏设备句柄,窗口设备句柄
                    
                    接下来的函数是DXUTCreateDevice。这个函数就是用来选择最优设备并创建的。
                  ①     设定参数中的回调函数和上下文,以备后用
                  ②     检查窗口是否被成功创建,否则再调用一次DXUTCreateWindow
                  ③    
                  枚举所有可能的显示模式。枚举过程非常复杂,用到了CD3DEnumeration中的一些包装函数,这些设备信息包括分辨率,颜色位深等等。这里会用到DXUTCreateDevice传进来的参数IsDeviceAcceptable

                  ④     如果命令行设定过显示模式,那么将刚才得到的信息覆盖。
                  ⑤     采用某种权重的算法找出最优显示模式(DXUTFindValidDeviceSettings)
                  ⑥    
                  切换设备。这里用到了DXUTCreateDevice传进来的参数ModifyDeviceSettings。切换设备时要考虑很多问题:比如需要暂时忽略WM_SIZE消息;只有在第一次创建设备的时候才用命令行参数;按照需要调用DXUTCreate3DEnvironment和DXUTReset3DEnvironment;分全屏和窗口设备重设;重设完了根据需要处理WM_SIZE消息;显示窗口,允许WM_SIZE消息等等

                   
                    最后是DXUTMainLoop。
                  ①     检查是否有重入问题
                  ②     设定进入主循环标志
                  ③     检查设备是否已经被成功创建,没创建的话用默认参数创建一次
                  ④     检查前面三个函数是否成功调用。汗,又是检查
                  ⑤     处理窗口消息,注意只有在没有消息处理的时候才调用DXUTRender3DEnvironment()
                  ⑥     在消息循环退出之后清除加速表。应该是类似SHIFT+X这种键盘加速表的清除吧
                  ⑦     更改主循环标志
                   
                    还是有必要看一下主消息循环中的DXUTRender3DEnvironment
                  ①     检查设备是否丢失
                  ②     在窗口模式下检查桌面分辨率位深设定,以便重设设备
                  ③     尝试重设设备DXUTReset3DEnvironment
                  ④     判断上次渲染到现在时间(elapsed time)决定是否要进行渲染
                  ⑤     调用用户的FrameMove函数
                  ⑥     调用用户的FrameRender函数
                  ⑦     调用Present函数
                  ⑧     更新当前Frame
                  ⑨     根据命令行检查是否需要关闭应用程序

主函数看完之后,剩下的就是一些回调函数了。要正确使用这些回调函数,除了知道它们的作用之外,还需要知道这些函数是何时被调用的。下面是调用顺序
                  
                   程序启动:InitApp →MsgProc →IsDeviceAcceptable
                  →ModifyDeviceSettings → OnCreateDevice →OnResetDevice → 渲染主循环
                  
                   渲染主循环:OnFrameMove → OnFrameRender  
                   改变设备:ModifyDeviceSettings → OnLostDevice
                  →根据需要调用OnDestroyDevice → OnResetDevice → 渲染主循环  
                   程序退出:OnLostDevice →OnDestroyDevice  
                  下面是各函数的作用:
                  InitApp 初始化一些图形控件和GUI的消息处理函数
                  OnCreateDevice 创建设备时的回调函数,用于创建D3DPOOL_MANAGED资源
                  OnResetDevice 重设设备时的回调函数,用于创建D3DPOOL_DEFAULT资源
                  OnFrameMove 动画实现处,常用于矩阵转换等操作
                  OnFrameRender 渲染实现处,常用于渲染场景
                  OnLostDevice 设备丢失时的回调函数,释放由OnResetDevice创建的资源
                  OnDestroyDevice 设备析构时的回调函数,释放由OnCreateDevice创建的资源
                  IsDeviceAcceptable 创建设备时用来对所有可用设备进行过滤的函数
                  ModifyDeviceSettings 更改设备时的回调函数,用于实现更改设备时所需做的其他操作
                  MsgProc 安排各空件处理消息的顺序
                  OnGUIEvent 程序控件绑定的消息处理回调函数


                  以上函数均可以更换名字,这里只是用框架默认的函数名字。//调用的时候对应好就可以了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DXUT框架剖析 DXUT框架剖析(14) 摘要: 控件是用户接口的重要组成部分,为了便于用户操作,为程序界面添加各种控件是非常好的方法。DXUT框架为在Direct3D程序中添加各种控件提供了支持。为了便于加载控件和处理各控件的消息,通常先在窗口中加载对话框,然后在对话框中添加响应的控件,由对话框来管理控件。为了统一管理各个对话框,还需要定义对话框资源管理器类CDXUTDialogResourceManager的一个对象,在程序开始时,调用各个对话框的Init函数和对话框资源管理对象进行初始化 DXUT框架剖析(13) 摘要: DXUT框架对文本绘制进行了封装,提供了类CDXUTHelper来简化文本显示,使用该接口大体分为3个步骤:初始化ID3DXSprite和ID3DXFont对象,显示文本,释放ID3DXSprite和ID3DXFont对象。 DXUT框架剖析(12) 摘要: DXUT暂停函数: DXUTPause:将框架的内部计数器和(或)渲染过程设为暂停状态。 DXUTRenderingPaused:检查当前设备的渲染状态是否处在暂停状态。 DXUTIsTimePaused:检查当前设备的计时器是否处在暂停状态。 DXUT框架剖析(11) 摘要: DXUT统计函数: DXUTGetFPS: 获取当前每秒提交的帧数。 DXUTGetFrameStats:获取一个指向字符串的指针,该字符串包括每秒帧数、分辨率、后台缓冲区格式、深度缓冲区格式。 DXUTGetDeviceStats:获取一个指向字符串的指针,该字符串包括当前设备类型、顶点运算行为和设备名。 DXUT框架剖析(10) 摘要: 管理DXUT框架的函数: DXUTResetFrameworkState: 将框架状态重置为初始默认状态,之前设置的框架状态改变将失效。 DXUTShutdown: 触发程序终止和清空框架。 DXUTGetExitCode: 获取框架的退出代码。 DXUT框架剖析(9) 摘要: 下面列出允许改变DXUT行为和获取内部变量的函数,这些函数在使用DXUT框架Direct3D程序中是非常实用的。 DXUT框架剖析(8) 摘要: Direct3D API的设计使程序能比较容易地处理各种错误,尽管大多数Direct3D API函数返回HTRSULT值,但只有一部分函数返回设备错误,如D3DERR_DEVICELOST或 D3DERR_DRIVERINTERNALERROR。但是通常的Direct3D应用程序使用多种API函数,当传递的参数不合要求时,将返回 D3DERR_INVALIDCALL。 当开发Direct3D应用程序时,应该检查所有的API调用是否成功,如果出现一个没有预测到的失败调用,应用程序应立即给出通知或记录该错误。使用这种方法,开发人员能很快发现哪些API函数的调用是不正确的。一个正确调用Direct3D API函数的应用程序应能安全地忽略大多数Direct3D API函数的失败调用,除了一些关键性的API函数,如Present()或TestCooperativeLevel(),这些函数返回的错误应用程序不能忽略。 DXUT框架剖析(7) 摘要: 框架也提供了帧事件,它在渲染过程中的每一帧被调用,应用程序应该注册并实现这些回调函数。 DXUT框架剖析(6) 摘要: 在窗口和设备创建好之后,应用程序需要使用消息循环处理窗口消息、更新和渲染场景、处理设备事件。应用程序可以实现自己的消息循环,也可以使用DXUT消息循环,注册相应的回调函数,可以让DXUT处理设备、帧消息事件。 为使用DXUT框架的消息循环,可以调用DXUTMainLoop()函数. DXUT框架剖析(5) 摘要: 应用程序可以通过DXUTSetCallbackDeviceChanging()设置回调函数来修改Direct3D设备的创建设置。 回调函数ModifyDeviceSettings()返回一个布尔值,如果应用程序返回 TRUE,DXUT框架继续像在正常情况下那样进行设备创建。如果返回FALSE,框架不能改变设备,如果已有一个设备,则继续使用当前设备。如果框架提出的请求是改变到一个应用程序不能使用的设备,应用程序可以拒绝该请求。例如,在一个多显示器配置中,默认情况下在显示器之间拖动窗口将使框架改变设备。但如果应用程序不能使用其他设备,它就必须拒绝这种改变并继续使用当前设备。 DXUT框架剖析(4) 摘要: 通常可以用标准的Direct3D方法Creat

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值