目录
一、索引缓冲区:
二、常量缓冲区:
一、索引缓冲区:
前言:
当我们要绘制如下图所示的立体图形棱台时,如果我们用顶点缓冲区来绘制的话,那我们需要绘制36个顶点。其中,我们知道棱台也就拥有8个顶点,这也说明了其余的28个顶点是重复的顶点。
能不能减少顶点的创建获得内存与性能的提升呢?那么,索引缓冲区的作用就来了!

1.下图是棱台的八个顶点

2.然后我们再把顶点数据放到索引数组里,我们就可以重复地利用顶点数据了,如下图所示

解释:如0,1,2就是利用第0个顶点,第1个顶点和第2个顶点绘制了一个三角形,所以这里,我们就利用了012,230六个顶点即两个三角形来绘制正面(四边形)
似乎特别容易理解,但是我们还没有创建索引缓冲区呢!我们需要索引缓冲区来和设备上下文打交道。
创建缓冲区:
//=======================================索引缓存的设置==============================================
// --------索引数组
DWORD 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;
ZeroMemory(&ibd, sizeof(ibd));
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof indices;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
// -------创建索引缓冲区
InitData.pSysMem = indices;
HR(m_pDevice->CreateBuffer(&ibd, &InitData, m_pIndexBuffer.GetAddressOf()));
//=======================================索引缓存的设置==============================================
设备创建缓冲区函数(和顶点缓冲区,常量缓冲区的创建是一样):CreateBuffer
参数1:缓冲区的描述
参数2:数据的来源/资源
参数3:取得缓冲区的指针
参数2中的资源,我们在前面已经分析过了,也就是把索引数组指针赋给InitData.pSysMem,再传给参数2。然后参数3用我们的成员变量m_pIndexBuffer来取得就好。这些都比较容易理解。参数1是获取缓冲区描述的指针,也就是说,我们需要对缓冲区进行描述。
缓冲区的描述:
结构原型:
typedef struct D3D11_BUFFER_DESC
{
UINT ByteWidth;
D3D11_USAGE Usage;
UINT BindFlags;
UINT CPUAccessFlags;
UINT MiscFlags;
UINT StructureByteStride;
}
D3D11_BUFFER_DESC;
1.ByteWidth:缓冲区大小
2.Usage:缓冲区的读取和写入方式,一般为D3D11_USIC_DEFAULT,这里使用D3D11_USAGE_IMMUTABLE
3.BindFlags:标识缓冲区将如何绑定到管道。
4.CPUAccessFlags:CPU访问标志,不访问CPU时,值为0
5.MiscFlags:杂项标识,未使用,则为0
6.StructureByteStride:每个元素的大小
到了这里,我们的索引缓冲区就创建成功了!
二、常量缓冲区:
前言:
一个常量缓冲区被用来向一个正在管线中执行的可编程着色器 应用程序提供常量信息。我们所说的常量,一般就是不会发生实质变化的量,那么我们就可以利用常量缓冲区进行世界矩阵,投影矩阵等变换。
//======================================常量缓冲区的设置=====================================================
// --------描述常量缓冲区
D3D11_BUFFER_DESC cbd;
ZeroMemory(&cbd, sizeof(cbd));
cbd.Usage = D3D11_USAGE_DYNAMIC;
cbd.ByteWidth = sizeof(ConstantBuffer);
cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
// --------新建常量缓冲区
HR(m_pDevice->CreateBuffer(&cbd, nullptr, m_pConstantBuffer.GetAddressOf()));
//--------- 初始化常量缓冲区
//
//返回单位矩阵
m_CBuffer.world = XMMatrixIdentity();
//因为HLSL中的矩阵按列主序,又由于world为单位阵,所以我们把view和proj进行转置
//矩阵转置
m_CBuffer.view = XMMatrixTranspose
//XMMatrixLookAtLH函数,基于左手坐标系,返回将点从世界空间转换为视图空间的视图矩阵,参1:摄像机的位置
// 参2:协调中心的位置
//参数3:相机向上的向量,表示3D坐标系中向上的坐标向量,这里表示屏幕由底向上递增的向上,这是一个规范化的坐标系
(XMMatrixLookAtLH
(
XMVectorSet(0.0f, 0.0f, -5.0f, 0.0f),
XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f),
XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f)//以世界空间的y轴作为摄像机“向上”的方向。因此(0, 1, 0)是平行于世界空间中y轴的一个单位向量
));
m_CBuffer.proj = XMMatrixTranspose(XMMatrixPerspectiveFovLH(XM_PIDIV2, AspectRatio(), 1.0f, 1000.0f));
//XMMatrixPerspectiveFovLH函数,返回透视投影矩阵,参数1:以弧度为单位的自顶向下视场角度,参数2:视宽比,参数3:距离近切飞机的距离,大于零。参数4:距离遥远的剪裁飞机,大于零
//======================================常量缓冲区的设置=====================================================
创建常量缓冲区的操作与创建索引缓冲区的操作类似,因此就不再展开。
我们来看下缓冲区的初始化。
准备工作:
1.这时候,我们就需要在HLSL头文件新增部分代码:

cbuffer :用于声明一个常量缓冲区
matrix :等价于 float4x4的矩阵
register(b0): 常量缓冲区位于寄存器索引为0的缓冲区
2.并改动HLSL头文件部分代码:

本文详细讲解了如何在DirectX11中使用索引缓冲减少顶点冗余,以及常量缓冲优化性能,通过键盘鼠标控制棱台旋转和缩放。涉及索引缓冲创建、常量缓冲初始化和实际应用示例。
最低0.47元/天 解锁文章
1029

被折叠的 条评论
为什么被折叠?



