本系列只针对书中每章节的编程练习题,不涉及书中的数学题,需要数学部分的解答请点击
对应原书 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}
};
******************/
题意:重做彩色立方体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);
题意:渲染一个顶部顶点是红色,底部顶点是绿色的金字塔
先说思路,确定物体在【物体坐标系(局部坐标系)】的五个顶点的位置,和相应的颜色,按渲染立方体的方式进行即可
有两种做法,一种最简单的是按原来彩色立方体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);
答:来自像素着色器的着色处理。
一个三角形,包含了三个顶点,通过这三个顶点连在一起,即叫做光栅化。GPU首先需要知道哪些像素需要被呈现,然后将这些需要呈现(三角形内部)像素激活并赋予颜色值,像素着色器就是为了计算哪些像素需要的颜色。像素着色器通过输入的像素颜色值,然后计算颜色并且将其返回给绘图管线。像素管线参数一般由几何着色器返回,假如没有几何着色器,那么就通过顶点着色器返回。
在光栅化过程中,需要对多边形进行着色(shading)。着色规定了如何利用顶点的颜色来计算构成图元的像素的颜色。
图元中个像素的颜色值由各顶点的颜色线性插值得到。各个颜色之间的平滑的过度,此种着色方式叫Gouraud 着色,也称平滑着色(smooth shading)