使用索引缓冲

使用索引缓冲进行绘制操作,还需要对我们之前编写的createCommandBuffers函数进行修改。首先我们需要将索引缓冲对象绑定到指令缓冲对象上,这和绑定顶点缓冲基本类似,不同之处是我们只能绑定一个索引缓冲对象。我们不能为每个顶点属性使用不同的索引,所以即使只有一个顶点属性不同,也要在顶点缓冲中多出一个顶点的数据。

vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);

vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16);

索引缓冲通过调用vkCmdBindIndexBuffer函数来进行绑定。vkCmdBindIndexBuffer函数以索引缓冲对象,索引数据在索引缓冲中的偏移,以及索引数据的类型作为参数。

仅仅绑定索引缓冲是不会起任何作用的,我们需要使用vkCmdDrawIndexed指令替换之前使用vkCmdDraw指令进行绘制操作:

vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);

vkCmdDrawIndexed函数的使用和vkCmdDraw函数类似。除了指令缓冲对象之外的前两个参数用于指定索引的个数和实例的个数。在这里,我们没有使用实例渲染,所以将实例个数设置为1。偏移值用于指定显卡开始读取索引的位置,偏移值为1对应索引数据中的第二个索引。倒数第二个参数是检索顶点数据前加到顶点索引上的数值。最后一个参数用于第一个被渲染的实例的ID,在这里,我们没有使用它。

现在编译运行程序可以看到下面的画面:

image

现在我们已经知道了如何使用索引缓冲来复用顶点数据。在之后的章节,我们载入的三维模型也需要使用索引缓冲来进行渲染。

之前提到,我们应该申请一大块内存来分配给多个缓冲对象使用,实际上,可以更进一步,使用一个缓冲对象通过偏移值来存储多个不同的顶点缓冲和索引缓冲数据。这样做之后,由于数据之间非常紧凑,可以更好地被缓存。对于没有同时进行的操作使用的内存块可以供多个对象复用,这种复用方式也被叫做混叠,许多Vulkan函数包含有标记参数可以用于显式地指定混叠处理。

本章节代码:

C++:

https://vulkan-tutorial.com/code/20_index_buffer.cpp

Vertex Shader:

https://vulkan-tutorial.com/code/17_shader_vertexbuffer.vert

Fragment Shader:

https://vulkan-tutorial.com/code/17_shader_vertexbuffer.frag