Ch7-2 初识索引缓冲区
本节的main.cpp对应示例代码中的:Ch7-2.hpp
这一节使用顶点缓冲区和索引缓冲区来绘制长方形。
索引绘制(indexed draw),是在绘制时根据索引缓冲区(index buffer)中的索引值取得相应顶点数据的绘制方式。
在之前Ch7-1.hpp用顶点缓冲区绘制三角形代码的基础上,使用顶点和索引缓冲区绘制长方形需要经历以下步骤:
绘制一个长方形需要几个顶点?当然4个!
一个长方形由两个三角形构成,所以以VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST为图元拓扑类型绘制时,必须要有6个顶点:
indexBuffer是VKBase+.h中的类。
绑定顶点缓冲区:
在渲染循环中,渲染通道开始后用vkCmdBindIndexBuffer(...)绑定索引缓冲区:
void VKAPI_CALL vkCmdBindIndexBuffer(...) 的参数说明 VkCommandBuffer commandBuffer 命令缓冲区的handle VkBuffer buffer 要被绑定的索引缓冲区的handle VkDeviceSize offset 索引缓冲区中被绑定范围到索引缓冲区开头的距离,单位是字节 VkIndexType indexType 索引类型,如不涉及扩展,可为VK_INDEX_TYPE_UINT16或VK_INDEX_TYPE_UINT32
用vkCmdDrawIndexed(...)进行索引绘制:
void VKAPI_CALL vkCmdDrawIndexed(...) 的参数说明 VkCommandBuffer commandBuffer 命令缓冲区的handle uint32_t indexCount 本次绘制所使用索引的个数 uint32_t instanceCount 要绘制的图形实例个数 uint32_t firstIndex 首个索引值在绑定的索引缓冲区中的索引 int32_t vertexOffset 索引缓冲区中的索引值加上vertexOffset即为最终使用的索引的数值 uint32_t firstInstance 首个图形实例的索引
简要说明vertexOffset的作用,如果顶点数据如下:
那么用
运行程序,你应该会看到以下图像:
相比只用顶点缓冲区进行绘制的方式,这么做得以在需要提供相同的顶点数据时,复用同一组数据。
使用顶点和索引缓冲区绘制长方形的流程
1.创建顶点缓冲区
2.创建索引缓冲区
3.在命令缓冲区中绑定顶点缓冲区并绘制
创建顶点缓冲区和索引缓冲区
vertex vertices[] = {
{ { -.5f, -.5f }, { 1, 1, 0, 1 } },
{ { .5f, -.5f }, { 1, 0, 0, 1 } },
{ { -.5f, .5f }, { 0, 1, 0, 1 } },
{ { .5f, .5f }, { 0, 0, 1, 1 } }
};
vertexBuffer vertexBuffer(sizeof vertices);
vertexBuffer.TransferData(vertices);
uint16_t indices[] = {
0, 1, 2,
1, 2, 3
};
indexBuffer indexBuffer(sizeof indices);
indexBuffer.TransferData(indices);
绑定顶点缓冲区和索引缓冲区
VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffer.Address(), &offset);
vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT16);
使用索引进行绘制
vkCmdDrawIndexed(commandBuffer, 6, 1, 0, 0, 0);
vertex vertices[] = {
{ { .0f, .0f }, { 0, 0, 0, 1 } },
{ { -.5f, -.5f }, { 1, 1, 0, 1 } },
{ { .5f, -.5f }, { 1, 0, 0, 1 } },
{ { -.5f, .5f }, { 0, 1, 0, 1 } },
{ { .5f, .5f }, { 0, 0, 1, 1 } }
};
vkCmdDrawIndexed(commandBuffer, 6, 1, 0, 1, 0)
绘制得到的会是相同的结果(offset为1,于是vertices[0]被跳过)。