文档章节

【转贴】DXUT 框架函数介绍

rise-worlds
 rise-worlds
发布于 2016/06/20 13:43
字数 2397
阅读 2
收藏 0
引用
DirectX SDK 2006学习笔记1——框架
友情提醒:所谓的框架是指SDK目录下\Samples\C++\Common路径下的DXUT系列函数包装。学习框架的前提是必须有足够的Windows API,GUI编程经验,必须熟悉Windows的消息机制,回调机制,最好有万行左右的C/C++编程经验。MFC在这里没有任何用处。另外我觉得最好在看程序之前对于D3D的所有概念有点了解,什么是vertex,texture,matrix,lighting,mesh等等,以及相关的数学概念。这些都可以在网上找到中文翻译,帮助你快速入门。
 
  DXSDK2006和2003版的比起来更新了不少东西,比如DirectX10,还有Managed
DirectX等等。不过我关心的还是D3D9。除了个别接口的更改之外,DXSDK2006还提供了一套图形控件的类库,它的界面还是很漂亮的:)如图:
 
  学习一个框架还是从它的入口学习比较方便,否则容易迷失在无穷无尽的API和层层包装之中。DXSDK2006的框架和2003版的DX9.0c框架有很大的不同。首先是2003版的框架中提供了一个CD3DApplication类,这个类对于初始化,清除,以及游戏窗口的创建,游戏主循环进行了包装。这是一个不错的类,不知道为什么在2006版中去掉了。不过不要紧,2006版的框架中提供的一些C包装函数已经足够了。在看这些函数之前,我们还是先来看看SDK目录下\Samples\C++ \Direct3D\Tutorials中有些什么吧。Tut01_CreateDevice是创建框架,这个程序不用框架,研究一下有助于了解D3D的大致工作流程。下面是winmain函数中的一部分。
 
    // Initialize Direct3D
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
         // Show the window
        ShowWindow( hWnd, SW_SHOWDEFAULT );
        UpdateWindow( hWnd );
 
        // Enter the message loop
        MSG msg;
        while( GetMessage( &msg, NULL, 0, 0 ) )
        {
            TranslateMessage( & msg );
             DispatchMessage( & msg );
        }
    }
  
  在消息循环之前有个初始化设备的函数InitD3D( hWnd ),其代码如下:
HRESULT InitD3D( HWNDhWnd )
{
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;
 
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( & d3dpp, sizeof(d3dpp) );
    d3dpp. Windowed = TRUE;
    d3dpp. SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp. BackBufferFormat = D3DFMT_UNKNOWN;
 
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, & d3dpp,
& g_pd3dDevice ) ) )
    {
         return E_FAIL;
    }
    return S_OK;
}
 
主要是调用 Direct3DCreate9 g_pD3D-> CreateDevice 这两个函数。查看 DXSDK 文档中关于 D3DPRESENT_PARAMETERS 的定义,大致了解一下。
接下来要关心的就是消息循环了,在回调函数 MsgProc中处理了两个消息,一个是 WM_DESTROY,里面调用了Cleanup函数,另一个是WM_PAINT函数,里面调用了Render函数。Cleanup函数很简单,就是调用D3D对象及其设备对象的Release函数释放资源,而Render函数就是D3D中最重要的函数了。
VOID Render()
{
    if( NULL==g_pd3dDevice)
        return;
 
    // Clear the backbuffer to a blue color
    g_pd3dDevice-> Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
   
    // Begin the scene
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // Rendering of scene objects can happen here
   
        // End the scene
        g_pd3dDevice-> EndScene();
    }
 
    // Present the backbuffer contents to the display
    g_pd3dDevice-> Present( NULL, NULL, NULL, NULL);
}
  主要调用的函数有BeginScene, EndScene和Present函数。
    对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
程序控件绑定的消息处理回调函数
 
  以上函数均可以更换名字,这里只是用框架默认的函数名字。


李锦俊 2006-11-18 09:08 发表评论

本文转载自:http://www.cnblogs.com/flying_bat/archive/2007/08/31/877260.html

下一篇: 字符转换
rise-worlds

rise-worlds

粉丝 3
博文 1755
码字总数 0
作品 0
深圳
程序员
私信 提问
如何使用DXUT框架

DXUT是什么? DXUT即DirectX Utility Library,它是微软为DirectX Samples写的一个框架,有了这个框架,Sample的构建就方便多了,这个框架实际上抽取了构建Sample的公共代码,比如处理窗口消...

吞吞吐吐的
2017/10/12
0
0
DirectX11--HR宏关于dxerr库的替代方案

DirectX11 With Windows SDK完整目录 欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。 综述 参考文章:https://blogs.msdn.microsoft.com/chuckw/2012/04/24/...

X_Jun
2018/12/24
0
0
Direct3D学习(三):光影贴图

刚看完了DXUT,拿来练练手 这个框架却实方便啊,终于不用写那些令人恶心的API函数了 光影贴图,说白了就是在纹理上表现出来光影效果,并不是实时计算的,所以适用于固定的场影平面,如地面,...

长平狐
2012/11/12
77
0
DXUT

DXUT 是一个建立在 Direct3D 之上的一个层,简化 了 Windows 和 Direct3D 的 API。它能帮助开发者建立一个更健壮、更易于生成的示例,原型,工具或游戏,...

大胖森
2015/04/30
724
0
【转贴】ProFTPD 1.2.x README(中文版)

原文见:http://www.1816.net/bbs/viewthread.php?tid=1725 正文如下:           ProFTPD 1.2.0 README(中文版) ============================ 吴伟; jeffwu_cn@hotmail.com 200......

zt371
2009/05/06
240
0

没有更多内容

加载失败,请刷新页面

加载更多

Tensorflow 2.0安装

Tensorflow2.0安装环境: Ubuntu 16.04或更高(64位) Windows 7或者更高(64位,且支持python3) 安装Tensorflow 2.0 GPU版本的需要安装NVIDIA相关软件包: NVIDIA驱动 :版本必须410.x或更...

JosiahMg
30分钟前
4
0
TL138/1808/6748F-EasyEVM开发板硬件、CPU、FLASH、RAM

TL138/1808/6748F-EasyEVM是广州创龙基于SOM-TL138/SOM-TL1808/SOM-TL6748F核心板开发的一款开发板。由于SOM-TL138/SOM-TL1808/SOM-TL6748核心板管脚兼容,所以此三个核心板共用同一个底板。...

Tronlong创龙
38分钟前
4
0
百度嵌入式AI解决方案EdgeBoard之内存驱动设计介绍

1. 背景介绍 由于 FPGA 具备可编程和高性能计算的特点,基于FPGA硬件的AI计算加速,正广泛地应用到计算机视觉处理领域。其中极具代表性的部署方式之一就是使用FPGA和CPU组合构成异构计算系统...

AI君
44分钟前
6
0
开放应用模型(OAM):全球首个云原生应用标准定义与架构模型

Kubernetes 项目作为容器编排领域的事实标准, 成功推动了诸如阿里云 Kubernetes (ACK)等云原生服务的迅速增长。但同时我们也关注到,Kubernetes 的核心 API 资源比如 Service、Deploymen...

Mr_zebra
47分钟前
4
0
《Linux操作系统-Exynos4412》编译和安装Busybox

开发环境:Exynos4412-iTOP-4412开发板 现在 Busybox 的配置已经完成了,接下来开始编译 Busybox,在 Ubuntu 的终端输入 “make”命令开始编译 Busybox,如下图。 下图为编译过程中的截图。 ...

书白
49分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部