DX12阅读笔记_第四章_End

4.4 计时和动画
为了正确地制作动画,我们将需要跟踪时间。我们需要测量动画帧之间流逝的时间。如果帧率很高,帧之间的时间间隔会很短;因此,我们需要一个高精度的定时器。
注意看GameTimer 类

4.4.1 计时器性能
性能计时器以称为计数的单位来衡量时间。 我们使用QueryPerformanceCounter函数获得性能计时器的当前时间值(以计数为单位)。
为了获得性能计时器的频率(每秒计数),我们使用QueryPerformanceFrequency函数。
QueryPerformanceCounter在Do Work 一头一尾使用再相减就得出Do work所消耗的时间计数。由于多处理器间不同的处理器的BIOS以及HAL的bug有可能得到不同的结果,所以最好加个SetThreadAffinityMask 函数这样主应用程序线程就不会切换到另一个处理器。

__int64 mBaseTime; 只设置一次程序开始时
__int64 mPausedTime; 累计的暂停时间
__int64 mStopTime; 暂停时的时间
__int64 mPrevTime; 记录最近一次开始的时间计数
__int64 mCurrTime; 当前时间计数

4.5 :关于本书的代码
个人的记录的一些点:
当窗口调整大小时,需要更改一些Direct3D属性,因为它们依赖于客户区域的尺寸。可以通过调用IDXGISwapChain::ResizeBuffers方法来调整后缓冲区的大小。深度/模板缓冲区需要被销毁,然后根据新的维度重新创建。D3DApp::OnResize()
除了缓冲区,其他属性依赖于客户区域的大小(例如,投影矩阵),因为这个方法是基于框架的,所以当窗口被调整大小时,可能需要更改自己的一些依赖于客户区域的大小代码。
渲染一帧所花费的时间比FPS更有用,因为当我们修改场景时,我们可以直观看到渲染一帧所花费的时间的增加/减少。Mspf = 1000 / fps。
此外,正如[Dunlop03]在他的文章《FPS versus Frame Time》中指出的,由于FPS曲线的非线性,使用FPS可能会产生误导的结果。例如,考虑情形(1):假设我们的应用程序以1000帧每秒的速度运行,需要1毫秒(毫秒)来渲染一个帧。如果帧速率下降到250帧/秒,那么渲染一帧需要4毫秒。现在考虑情况(2):假设我们的应用程序以100帧每秒的速度运行,渲染一帧需要10毫秒。如果帧速率下降到大约76.9 FPS,那么渲染一帧大约需要13毫秒。在这两种情况下,每帧的渲染都增加了3毫秒,因此这两种情况都代表了渲染一帧所花费的时间的增加。读取FPS就不那么直观了。从1000帧下降到250帧似乎比从100帧下降到76.9帧要剧烈得多;然而,正如我们刚才所展示的,它们实际上代表了渲染一个帧所花费的时间的相同增长。

如果应用程序暂停,我们就不会更新应用程序代码,而是将一些CPU周期释放回操作系统;这样,当应用程序处于非活动状态时,它就不会占用CPU周期。
在这里插入图片描述

如果用户拖动调整客户端的缩放条,我们必须小心,因为拖动调整大小条发送连续的WM_SIZE消息,而且我们不想连续调整缓冲区的大小。因此,如果我们确定用户通过拖动来调整大小,我们实际上什么也不做(除了暂停应用程序),直到用户完成拖动调整大小条。我们可以通过处理WM_EXITSIZEMOVE消息来做到这一点。此消息在用户释放调整大小条时发送。
在这里插入图片描述

书中最后总结部分翻译:
1: 可以将Direct3D看作是程序员和图形硬件之间的中介。例如,程序员调用Direct3D函数来将资源视图绑定到硬件呈现管道、配置呈现管道的输出以及绘制3D几何图形。
2: 组件对象模型(COM)是一种允许DirectX独立于语言并具有向后兼容性的技术。Direct3D程序员不需要知道COM的细节和它是如何工作的;他们只需要知道如何获取COM接口以及如何释放它们。
3:一维纹理就像数据元素的一维数组,二维纹理就像数据元素的二维数组,而三维纹理就像数据元素的三维数组。纹理的元素必须具有由DXGI_FORMAT枚举类型的成员描述的格式。
纹理通常包含图像数据,但是它们也可以包含其他数据,比如深度信息(例如深度缓冲)。
GPU可以对纹理做特殊的操作,比如过滤和多采样。
4: 为了避免在动画中闪烁,最好将整个动画帧绘制到称为后台缓冲区的离屏纹理中。一旦在后缓冲为给定帧的动画将整个场景绘制完后,它将作为一个完整的帧呈现在屏幕上;这样,玩家就不会观看到一帧动画被绘制的过程。在帧被绘制到后缓冲之后,后缓冲和前缓冲的角色就反转了:后缓冲成为前缓冲,前缓冲成为下一帧动画的后缓冲。前后缓冲区的角色交换称为递交。前端和后端缓冲区形成交换链,由IDXGISwapChain接口表示。使用两个缓冲区(前和后)称为双缓冲。
5: 假设场景对象是不透明的,离摄像机最近的点会遮挡它们后面的任何点。深度缓冲是一种确定场景中最接近相机的点的技术。这样,我们就不必担心绘制场景对象的顺序了。
6: 在Direct3D中,资源不直接绑定到管道。相反,我们通过指定将在draw调用中引用的描述符来将资源绑定到呈现管道。描述符对象可以被认为是一种轻量级的结构,它可以识别并向GPU描述资源。可以为单个资源创建的不同描述符。这样,就可以从不同的角度看待单一的资源;例如,将其绑定到呈现管道的不同阶段,或者作为不同的DXGI_FORMAT来解释资源。应用程序创建形成描述符内存支持的描述符堆。
7: ID3D12Device是Direct3D的主要接口,可以看作是我们物理图形设备硬件的软件控制器;
通过它,我们可以创建GPU资源,并创建其他专用接口来控制图形硬件和指示它做事情。
8: GPU有一个命令队列。CPU使用命令列表通过Direct3D API向队列提交命令。命令指示GPU做一些事情。所提交的命令直到到达队列的最前面才会被GPU执行。如果命令队列为空,GPU将空闲,因为它没有任何工作要做; 另一方面,如果命令队列太满,CPU将在某个时候不得不空闲而等待GPU赶上。这两种情况都没有充分利用系统的硬件资源。
9: GPU是系统中与CPU并行运行的第二处理器。有时CPU和GPU需要同步。例如,如果GPU在其队列中有一个引用资源的命令,CPU必须不修改或销毁该资源,直到GPU完成这条指令。任何导致一个处理器等待和空闲的同步方法都应该最小化,因为这意味着我们没有充分利用这两个处理器。
10: 对于模式构建debug,我们启用调试层(debugController->EnableDebugLayer())。当调试层启用时,Direct3D将向vc++输出窗口发送debug消息。

至此第四章结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值