现在的位置: 首页 > 综合 > 正文

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

2018年04月09日 ⁄ 综合 ⁄ 共 4025字 ⁄ 字号 评论关闭

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

 

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

 

        上一期的地址:

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


        这一期我们专门来研究第6章的习题。虽然数目比较多,但是大部分还是很容易的。注意我说的是“大部分”!

 

习题解答:

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

        这里的习题都不难,不过要好好做才能够掌握知识呀!

 

习题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个表示偏移的比特数的参数。当然我这只是给出了最简单、最容易想到的一种方式;甚至还不一定对,因为这个顶点太过复杂了,也没法轻易地拿一个例子检测出来。你还可以玩点花招,比如把前面的名字都改了,只要你自己能够认得就行。

 

习题2

        这个题目貌似很简单的,似乎题目本身已经把答案给给出了?不过如果你这么认为的话,那么你就中招了!我花了很长时间才把这个问题搞定!大致来说,有这么几个注意事项:

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

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

 

习题5

        这一题是一个问答题,很简单,自己去第5章寻找答案吧!

 

习题6

        这道题也很简单;当然不是仅仅在.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则为正面消隐)之间进行切换了。运行结果如下图所示:

        这道题还是很简单的,大部分的改动是在.fx文件中进行的。在C++ 代码中只需要添加对输入的判断就行了。值得一提的是,在DX 11 中,不再需要像在DX 9 中那样,当你选择另外一个technique 之后,还需要调用SetTechnique 函数来使其生效了。

 

习题10

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

        关键在于后面的“注意”。然后要注意的是,那里给出的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章习题答案下载地址

抱歉!评论已关闭.