常量缓冲区和索引缓冲区
前言
在上篇文章中,我们成功在程序中心渲染了一个三角形。我们创建顶点缓冲区时,我们使用顶点位置直接在投影空间,这样我们就不必执行任何变化,就可以在屏幕上输出。但是我们如果想让物体在D3D中动起来,必须就在每一帧前把顶点缓冲中的数据变成物体动完后再投影空间。但是那样太麻烦了,我们应该输入的就是模型空间的位置,再在着色器中变换位置以造成动画效果。在本篇中,我们了解一些新知识用来实现我们的效果。
修改常量缓冲区
由于我们开始动起来,所以我们实际上就进入了3D空间。因此我们将之前的平面三角形更改为3维物体立方体。
// ****************** // 设置立方体顶点 // 5________ 6 // /| /| // /_|_____/ | // 1|4|_ _ 2|_|7 // | / | / // |/______|/ // 0 3 VertexPosCol vertices[] = { { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) }, { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) }, { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) }, { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) }, { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) }, { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) }, { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) }, { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) } };
如果你注意到,实际上我知识指定了立方体的8个顶点,我们并没有描述各个三角形。如果我们原样输入,我们是无法得到我们想要的结果的。
在立方体上,许多三角形共享相同的顶点,如果一遍又一遍的定义三角形的顶点将会浪费空间。因此,有一个方法只指定八个点,然后让D3D知道要为三角形选择哪些点。这就是索引缓冲区完成的。
索引缓冲区
使用索引缓冲区代替指定顺序绘制,可以有效减少顶点缓冲区占用的空间。避免提供大量重复的顶点数据。
索引数组初始化
// 索引数组 WORD indices[] = { // 正面 0, 1, 2, 2, 3, 0, // 左面 4, 5, 1, 1, 0, 4, // 顶面 1, 5, 6, 6, 2, 1, // 背面 7, 6, 5, 5, 4, 7, // 右面 3, 2, 6, 6, 7, 3, // 底面 4, 0, 3, 3, 7, 4 };
然后填充缓冲区描述信息并创建索引缓冲区
D3D11_BUFFER_DESC ibd = {}; ibd.Usage = D3D11_USAGE_DEFAULT; ibd.ByteWidth = sizeof(indices); ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA initData = {}; initData.pSysMem = indices; g_pD3D11Device->CreateBuffer(&ibd, &initData, g_pIndiceBuffer.GetAddressOf()))
就像顶点缓冲区一样,我们得到索引缓冲区后,还需要把它绑定到渲染管道上。
void ID3D11DeviceContext::IASetIndexBuffer( ID3D11Buffer *pIndexBuffer, // [In]索引缓冲区 DXGI_FORMAT Format, // [In]数据格式 UINT Offset); // [In]字节偏移量
其中Format
所以我们这里示例如下;
g_pImmediateContext->IASetIndexBuffer(g_pIndiceBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);
修改顶点着色器
我们需要在顶点着色器内完成一个顶点从模型空间转换到