【DX11习题学习二】第六章练习 Drawing in Direct3D(上)

本系列只针对书中每章节的编程练习题,不涉及书中的数学题,需要数学部分的解答请点击


对应原书 P264 6.15EXERCISES

1. Write down the D3D10_INPUT_ELEMENT_DESC array for the following vertex structure:
struct Vertex
{
XMFLOAT3 Pos;
XMFLOAT3 Tangent;
XMFLOAT3 Normal;
XMFLOAT2 Tex0;
XMFLOAT2 Tex1;
XMCOLOR Color;
};


题意:将Vertex结构体修改成上面的格式

第一步:修改Vertex格式

/*********练习1*********/
struct Vertex
{
	XMFLOAT3 Pos;
	XMFLOAT3 Tangent;
	XMFLOAT3 Normal;
	XMFLOAT2 Tex0;
	XMFLOAT2 Tex1;
	XMFLOAT4 Color;
};
/*********************	
	原来Demo
struct Vertex
{
	XMFLOAT3 Pos;
	XMFLOAT4 Color;
};
*********************/
第二步:修改Vertex数组的内容

/*
	Vertex vertices[] =
    {
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::White   },
		{ XMFLOAT3(-1.0f, +1.0f, -1.0f), (const float*)&Colors::Black   },
		{ XMFLOAT3(+1.0f, +1.0f, -1.0f), (const float*)&Colors::Red     },
		{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Green   },
		{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Blue    },
		{ XMFLOAT3(-1.0f, +1.0f, +1.0f), (const float*)&Colors::Yellow  },
		{ XMFLOAT3(+1.0f, +1.0f, +1.0f), (const float*)&Colors::Cyan    },
		{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Magenta }
    };
	*/
	/***********修改如下,关于Tangent、Normal、Tex0、Tex1都是乱填的没有意义*************/
    Vertex vertices[] =
    {
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(-1.0f, -1.0f, -1.0f),XMFLOAT3(-1.0f, -1.0f, -1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f),(const float*)&Colors::White },
		{ XMFLOAT3(-1.0f, +1.0f, -1.0f), XMFLOAT3(-1.0f, +1.0f, -1.0f),XMFLOAT3(-1.0f, +1.0f, -1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f),(const float*)&Colors::Black },
		{ XMFLOAT3(+1.0f, +1.0f, -1.0f), XMFLOAT3(+1.0f, +1.0f, -1.0f),XMFLOAT3(+1.0f, +1.0f, -1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f), (const float*)&Colors::Red },
		{ XMFLOAT3(+1.0f, -1.0f, -1.0f), XMFLOAT3(+1.0f, -1.0f, -1.0f),XMFLOAT3(+1.0f, -1.0f, -1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f),(const float*)&Colors::Green },
		{ XMFLOAT3(-1.0f, -1.0f, +1.0f), XMFLOAT3(-1.0f, -1.0f, +1.0f),XMFLOAT3(-1.0f, -1.0f, +1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f),(const float*)&Colors::Blue },
		{ XMFLOAT3(-1.0f, +1.0f, +1.0f),XMFLOAT3(-1.0f, +1.0f, +1.0f),XMFLOAT3(-1.0f, +1.0f, +1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f), (const float*)&Colors::Yellow },
		{ XMFLOAT3(+1.0f, +1.0f, +1.0f), XMFLOAT3(+1.0f, +1.0f, +1.0f),XMFLOAT3(+1.0f, +1.0f, +1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f),(const float*)&Colors::Cyan },
		{ XMFLOAT3(+1.0f, -1.0f, +1.0f),  XMFLOAT3(+1.0f, -1.0f, +1.0f), XMFLOAT3(+1.0f, -1.0f, +1.0f),XMFLOAT2(0.0f, 0.0f), XMFLOAT2(0.0f, 0.0f), (const float*)&Colors::Magenta }
	};
第三步,最重要的,调整D3D11_INPUT_ELEMENT_DESC的输入格式,第五个参数修改为52,偏移52字节,因为前面Vertex中前5个变量字长(3+3+3+2+2)*4=52

/*********练习1***********/
	D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 52, D3D11_INPUT_PER_VERTEX_DATA, 0 }
	};
	/*******************原来的Demo
	// Create the vertex input layout.
	D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};
	******************/


2.Redo the Colored Cube demo, but this time use two vertex buffers (and two input slots) to feed the pipeline with vertices, one that stores the position element and the other that stores the color element. Your D3D11_INPUT_ELEMENT_DESC array will look like this:
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0,
D3D11_INPUT_PER_VERTEX_DATA, 0}
};
The position element is hooked up to input slot 0, and the color element is hooked up to input slot 1. Moreover note that the D3D11_INPUT_ELEMENT_DESC::AlignedByteOffsetis 0 for both elements; this is because the position and color elements are no longer interleaved in a single input slot.

题意:重做彩色立方体Demo,这次要采用两个顶点缓存(和两个输入槽)放进管线中,D3D11_INPUT_ELEMENT_DESC如上所示

问题有点麻烦,要创建两个顶点缓存,也就是需要达到下面的样子

/**************原来的demo
    D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(Vertex) * 8;
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
	vbd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = vertices;
    HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB));
	***************/
	//创建第一个顶点缓存
	D3D11_BUFFER_DESC vbd;
	vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = sizeof(VertexPos) * 8;
	vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vbd.CPUAccessFlags = 0;
	vbd.MiscFlags = 0;
	vbd.StructureByteStride = 0;
	D3D11_SUBRESOURCE_DATA vinitData;
	vinitData.pSysMem = verticesPos;
	HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB[0]));
	//创建第二个顶点缓存
	D3D11_BUFFER_DESC vbd2;
	vbd2.Usage = D3D11_USAGE_IMMUTABLE;
	vbd2.ByteWidth = sizeof(VertexColor) * 8;
	vbd2.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vbd2.CPUAccessFlags = 0;
	vbd2.MiscFlags = 0;
	vbd2.StructureByteStride = 0;
	D3D11_SUBRESOURCE_DATA vinitData2;
	vinitData2.pSysMem = verticesColor;
	HR(md3dDevice->CreateBuffer(&vbd2, &vinitData2, &mBoxVB[1]));
然后设置 两个输入槽(第0槽和第1槽),让设备对象创建这样的输入格式

D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
	{
		{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
		{"COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}
	};

	// Create the input layout
    D3DX11_PASS_DESC passDesc;
    mTech->GetPassByIndex(0)->GetDesc(&passDesc);
	HR(md3dDevice->CreateInputLayout(vertexDesc, 2, passDesc.pIAInputSignature, 
		passDesc.IAInputSignatureSize, &mInputLayout));

 此时我们由上面的代码思路知道创建两个顶点缓存,然后仍需要注意一下在DrawScene函数(不断被调用重新绘制帧的函数)中修改IASetVertexBuffers函数(具体参数意思,参考MSDN) 
  

    //UINT stride = sizeof(Vertex);
    //UINT offset = 0;
	UINT stride[2] = { sizeof(VertexPos), sizeof(VertexColor) };
	UINT offset[2] = { 0,0 };
	/*******练习2*********/
    //md3dImmediateContext->IASetVertexBuffers(0, 2, &mBoxVB, &stride, &offset);
	// 
	//=========================================================================
	md3dImmediateContext->IASetVertexBuffers(0, 2, mBoxVB, stride, offset);
	//=========================================================================


好了,其实我的思路是倒着来的,正常思路应该先创建两个类中创建
ID3D11Buffer* mBoxVB[2];

记得在构造函数中初始化

	mBoxVB[0] = NULL;
	mBoxVB[1] = NULL;

以及重新定义Vertex结构体
struct VertexPos
{
	XMFLOAT3 Pos;
};
struct VertexColor
{
	XMFLOAT4 Color;
};
修改Vetex数据格式

VertexPos verticesPos[] =
	{
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f) },
		{ XMFLOAT3(-1.0f, +1.0f, -1.0f) },
		{ XMFLOAT3(+1.0f, +1.0f, -1.0f) },
		{ XMFLOAT3(+1.0f, -1.0f, -1.0f) },
		{ XMFLOAT3(-1.0f, -1.0f, +1.0f) },
		{ XMFLOAT3(-1.0f, +1.0f, +1.0f) },
		{ XMFLOAT3(+1.0f, +1.0f, +1.0f) },
		{ XMFLOAT3(+1.0f, -1.0f, +1.0f) }
	};

	VertexColor verticesColor[] =
	{
		{ (const float*)&Colors::White },
		{ (const float*)&Colors::Black },
		{ (const float*)&Colors::Red },
		{ (const float*)&Colors::Green },
		{ (const float*)&Colors::Blue },
		{ (const float*)&Colors::Yellow },
		{ (const float*)&Colors::Cyan },
		{ (const float*)&Colors::Magenta }
	};

别忘记要释放引用

	ReleaseCOM(mBoxVB[1]);
	ReleaseCOM(mBoxVB[2]);


3. Draw
(a) a point list like the one shown in Figure 5.13a.
(b) a line strip like the one shown in Figure 5.13b.
(c) a line list like the one shown in Figure 5.13c.
(d) a triangle strip like the one shown in Figure 5.13d.
(e) a triangle list like the one shown in Figure 5.14a.

题意:以point list、line strip、line list、triangle strip、triangle list样式显示图案

这题比较简单,

设置成员变量

	D3D11_PRIMITIVE_TOPOLOGY  mPrimitiveTopology;
在构造函数中初始化为

mPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
在UpdateScene函数(负责每一帧更新的逻辑的函数)添加,按键数字键0~4即可出现相应的效果

	if (GetAsyncKeyState('0') & 0x8000)
		mPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;;
	if (GetAsyncKeyState('1') & 0x8000)
		mPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
	if (GetAsyncKeyState('2') & 0x8000)
		mPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
	if (GetAsyncKeyState('3') & 0x8000)
		mPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
	if (GetAsyncKeyState('4') & 0x8000)
		mPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
在DrawScene函数中最后改一下即可

md3dImmediateContext->IASetPrimitiveTopology(mPrimitiveTopology);

4. Construct the vertex and index list of a pyramid, as shown in Figure 6.19, and draw it. Color the base vertices green and the tip vertex red.

题意:渲染一个顶部顶点是红色,底部顶点是绿色的金字塔

先说思路,确定物体在【物体坐标系(局部坐标系)】的五个顶点的位置,和相应的颜色,按渲染立方体的方式进行即可

有两种做法,一种最简单的是按原来彩色立方体Demo,把y坐标为正4个的顶点都设为同一个坐标(0.0,1.0,0.0),设置好相应颜色即可渲染出金字塔

另一只老实点做法:

修改顶点位置和索引顺序,和修改顶点缓存和索引缓存的创建设置

	// Create vertex buffer
    Vertex vertices[] =
    {//一共5个面
		{ XMFLOAT3(0.0f,+1.0f, 0.0f), (const float*)&Colors::Red },			 //金字塔顶部顶点,索引号为0
		{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Green },    //金字塔底部左上顶点,索引号为1
		{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Black },    //金字塔底部右上顶点,索引号为2
		{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Blue }, 	     //金字塔底部右下顶点,索引号为3
		{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::Magenta }, //金字塔底部左下顶点,索引号为4
    };

    D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(Vertex) * 5;
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
	vbd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = vertices;
    HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB));


	// Create the index buffer
	//注意顺时针,一共18个索引点
	UINT indices[] = {
		// back face
		0, 1, 2,
		//  right face
		0, 2, 3,
		// front face
		0, 3, 4,
       //  left face
		0, 4, 1,
		// bottom face
		1, 3, 2,
		1, 4, 3,
	};

	D3D11_BUFFER_DESC ibd;
    ibd.Usage = D3D11_USAGE_IMMUTABLE;
    ibd.ByteWidth = sizeof(UINT) * 18;
    ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;
	ibd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA iinitData;
    iinitData.pSysMem = indices;
    HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mBoxIB));
还要记得修改

		// 18 indices for the box.
		md3dImmediateContext->DrawIndexed(18, 0, 0);

5. Run the “Box” demo, and recall that we specified colors at the vertices only. Explain how pixel colors were obtained for each pixel on the triangle.
题意:彩色立方体Demo中,我们只是指明顶点的颜色,三角形区域内的其他像素颜色是怎么来的呢?

答:来自像素着色器的着色处理。
       一个三角形,包含了三个顶点,通过这三个顶点连在一起,即叫做光栅化。GPU首先需要知道哪些像素需要被呈现,然后将这些需要呈现(三角形内部)像素激活并赋予颜色值,像素着色器就是为了计算哪些像素需要的颜色。像素着色器通过输入的像素颜色值,然后计算颜色并且将其返回给绘图管线。像素管线参数一般由几何着色器返回,假如没有几何着色器,那么就通过顶点着色器返回。
      在光栅化过程中,需要对多边形进行着色(shading)。着色规定了如何利用顶点的颜色来计算构成图元的像素的颜色。
图元中个像素的颜色值由各顶点的颜色线性插值得到。各个颜色之间的平滑的过度,此种着色方式叫Gouraud 着色,也称平滑着色(smooth shading)



题意:将Vertex结构体修改成上面的格式

你可能感兴趣的:(DirectX11)