• DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)


            本文由哈利_蜘蛛侠原创,转载请注明出处。有问题欢迎联系2024958085@qq.com

            注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候,会使用章节号而非页码。相同的情况适合于“龙书”第二版。

            上一期的地址:

    DX 11游戏编程学习笔记之7 


            这一期我们专门来研究第6章的习题。

    尽管数目比較多,可是大部分还是非常easy的。注意我说的是“大部分”!

     

    习题解答:

    ===============================================================================

            这里的习题都不难,只是要好好做才可以掌握知识呀!

    习题1

    <pre name="code" class="cpp">D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
    {
    	{ "POSITION",     0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    	{ "TANGENT",      0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    	{ "NORMAL",       0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    	{ "TEXTURECOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    	{ "TEXTURECOORD", 1, DXGI_FORMAT_R32G32_FLOAT,    0, 44, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    	{ "COLOR",        0, DXGI_FORMAT_R8G8B8A8_UNORM,  0, 52, D3D11_INPUT_PER_VERTEX_DATA, 0 }
    }
    
    

            要注意的是每一个成员中第3个表示格式的參数和第5个表示偏移的比特数的參数。当然我这仅仅是给出了最简单、最easy想到的一种方式;甚至还不一定对。由于这个顶点太过复杂了,也没法轻易地拿一个样例检測出来。

    你还可以玩点花招,比方把前面的名字都改了,仅仅要你自己可以认得即可。

    习题2

            这个题目貌似非常easy的,似乎题目本身已经把答案给给出了?只是假设你这么觉得的话。那么你就中招了。我花了非常长时间才把这个问题搞定!大致来说,有这么几个注意事项:

    1、  要建立一个ID3D11Buffer* 类型的数组(在此题中是2维数组)。

    2、  要建立两个结构体来代表两个“不完整”的顶点,比方说建立VertexPos 来存储位置,而VertexColor 来存储颜色;

    3、  用新的顶点数据来给这两个ID3D11Buffer* 对象进行赋值;

    4、  在DrawScene 函数中调用IASetVertexBuffers 时,应该这样写:

    md3dImmediateContext->IASetVertexBuffers(0,2, mBoxVB, stride, offset);

    当中stride 和offset 分别定义例如以下:

    UINT stride[2] = {sizeof(VertexPos), sizeof(VertexColor) };

    UINT offset[2] = { 0,0 };

    习题3

            这道题让我们画五幅图。我们细致观察就会发现。这五幅图有非常大的相似性。详细就是前面四幅图都是用八个顶点,而第五幅图是用九个顶点。于是我就定义了9个顶点,然后通过用户的输入来切换不同的图元拓扑类型。详细就是数字键0、1、2、3、4分别相应这五幅图的图元拓扑类型。另外注意的是,在第五幅图的情况下,我们绘制9个顶点,而其它情况下我们仅仅绘制8个顶点。另外为了避免三角形消失掉,注意要关闭背面消隐。

            我给大家展示两幅图来挑起大家的兴趣:

            当然你也能够定义5个顶点缓存来分别存放这五个图形的顶点。

    只是我这样的方法非常省事儿,不是吗?

    习题4

            这道题非常easy,其实比书上的Box demo 还要简单,由于面数少了。只是为了更加好看,更加容易区分不同的面,所以我对每一个顶点都赋予了不同的颜色。以下是程序执行时的一张截图:

    习题5

            这一题是一个问答题。非常easy,自己去第5章寻找答案吧!

    习题6

            这道题也非常easy;当然不是只在.fx 文件里加入题目中给出的两行代码就能够了,由于你还得要在constant buffer 中加入一个表示总时间的变量。

    这就意味着我们必须在C++ 程序中进行对应的代码加入。整体来说这道题没什么可说的,只是这效果非常惊人。我就不截图了,大家自己执行一下看看,然后相信大家看了之后会非常有食欲的^_^

            另外我在这里顺便把第12题给做了。第12题的两个答案都是肯定的。相信大家思考一下就行知道是为什么了。

    习题7

            这道题让我们反复之前在Shapes demo 中玩过的把戏。只是这次是让我们将一个正方体和一个四棱锥(金字塔)的顶点缓存和索引缓存分别合并起来。

    这个尽管看上去不难,可是却让我花费了非常长时间。

    最后发现。原来是在用vector 装载合并的顶点(和索引)时,最后对D3D11_SUBRESOURCE_DATA 进行赋值的时候,要这样写:

    vinitData.pSysMem =&vertices[0];

    而不是这样写:

    vinitData.pSysMem =&vertices;

            后面那样尽管能够编译成功,甚至能够执行起来。可是得到的结果一定不是你想要的那样子T_T

            给一张程序执行时的截图:


    习题8和习题9

            这两道题非常相似。所以我就放在一起讲了。实际上习题9已经包括了习题8的内容了。所以我就仅仅讲习题9了。另外因为大家在习题3中已经见识到了怎样在C++ 程序中设置rasterization render state 了。所以我们这里仅仅做了在effect file 中对rasterization render state 进行设置的部分。

    程序执行后,按数字键1和2就能够在两种消隐模式(按下1则关闭背面消隐。按下2则为正面消隐)之间进行切换了。

    执行结果例如以下图所看到的:




            这道题还是非常easy的。大部分的修改是在.fx文件里进行的。在C++ 代码中仅仅须要加入对输入的推断即可了。

    值得一提的是。在DX 11 中。不再须要像在DX 9 中那样,当你选择另外一个technique 之后,还须要调用SetTechnique 函数来使其生效了。

    习题10

            这道题让我们改动顶点的结构,不用XMFLOAT4来代表颜色,而是用更加节省内存的XMCOLOR 来代表。似乎非常easy?不不不,你实际去做做就知道了。

            关键在于后面的“注意”。

    然后要注意的是。那里给出的ArgbToAbgr 函数不是某个头文件中已经定义好的函数;这个函数须要我们自己加入到代码之中。

            这个函数是将颜色从ARGB 格式转化到AGBR 格式时要用到的。之所以须要这个转化,是由于Direct3D 使用的是AGBR 格式。可是XMCOLOR 使用的是ARGB 格式。而且ARGB 也是我们比較喜欢使用的格式。比方说,在ARGB 格式中。0xffff0000表示100%的红色;可是假设你不进行转换的话,直接将这个数值写到顶点中,那么终于的结果是100% 的蓝色。

            另外尽管顶点结构中表示颜色的是XMCOLOR类型的变量。而HLSL 中用float4 表示颜色,可是你不须要做不论什么额外的工作来将XMCOLOR 转换成float4 了。

            当然,以上仅仅是我的个人理解。可能不一定对;欢迎各位提出宝贵意见!

    习题11

            这样的设置视口的题在第4章的习题6那里已经讲过了,所以我就不再赘述了。以下是我程序执行时的一个截图:


    习题12

            參见习题6

    习题13

            这道题让我们使用RSSetScissorRects 函数来实现一种类似于屏幕裁剪的功能。

    这道题应该没有不论什么问题了吧。只是有一点须要注意:即使你设置了不只一个scissor rectangles,那么你也只会看到一个子窗体被显示出来。例如以下图所看到的:


            为什么会这样呢?我为这个问题纠结了好几十分钟。最后最终在SDK 文档中找到了答案:

    Which scissor rectangle to use is determined by the SV_ViewportArrayIndex semantic output by a geometry shader (see shader semantic syntax). If a geometry shader does not make use of the SV_ViewportArrayIndex semantic then Direct3D will use the first scissor rectangle in the array.

            另外,我的这些scissorrectangle 的位置和大小是与窗体大小相关的,我希望当窗体尺寸被调节时它们也会随着被改变。

    所以我就把这几个设置语句放在了OnResize 函数中了。

    习题14

            这个题目不难,仅仅是做起来有点麻烦而已。

    当然事实上书上的Shapes demo 比这一题要难得多。所以我们在那个的基础上进行增删补操作就能够了。

            我加入了对输入的响应,而且还能够改变渲染状态。整体来说,数字键0、1、2、3分别相应0、1、2、3级细分,而W 键和S 键能够在两种填充模式之间进行切换。

    以下是程序执行时的两幅截图:



    ===============================================================================

            当然,最后我不会忘了给你们这些代码的下载地址的:

    第6章习题答案下载地址


  • 相关阅读:
    0593. Valid Square (M)
    0832. Flipping an Image (E)
    1026. Maximum Difference Between Node and Ancestor (M)
    0563. Binary Tree Tilt (E)
    0445. Add Two Numbers II (M)
    1283. Find the Smallest Divisor Given a Threshold (M)
    C Primer Plus note9
    C Primer Plus note8
    C Primer Plus note7
    C Primer Plus note6
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5281285.html
Copyright © 2020-2023  润新知