在 Vulkan 中绘制多个带有纹理的对象
Draw multiple objects with their textures in Vulkan
我想绘制一个包含多个对象的场景,每个对象都有自己的统一缓冲区和纹理,目前我可以使用动态统一缓冲区绘制多个对象,我这样做的方式是遍历动态统一缓冲区命令缓冲区记录期间的对象偏移和顶点索引,这样我告诉 Vulkan 使用特定的全局矩阵绘制模型,但是我不知道如何在此操作期间绑定纹理信息,以便 Vulkan 知道使用正确的该对象的纹理,在我的示例中,我有四个具有四种不同纹理的框。
您可以使用vkCmdBindDescriptorSets 绑定新纹理。
确保使用纹理绑定的描述符集是布局中编号最高的集。
当您使用 firstset > 0 调用 vkCmdBindDescriptorSets 时,绑定描述符集索引 [0 ... firstSet-1]
将保持不变。
到目前为止,我设法使用以下方法绘制了多个对象:-
注意:所有模型的所有顶点属性信息都存储在一个缓冲区中,该缓冲区是按模型组织的。
1.using 一个描述符集有两个绑定(一个用于 UBO,一个用于纹理采样器),UBO 的类型是动态的,以适应所有对象的 UBO,在命令缓冲区记录过程中,您只需遍历要绘制的指定顶点属性对应的Dynamic UBO数组
优点:高效快速
缺点:所有对象将具有相同的纹理(适用于多次渲染相同的模型,每次使用不同的ubo)
绘制过程
for (uint32_t j = 0; j < m.geometryCount; j++)
{
uint32_t dynamicOffset = j * 256;
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 1, &dynamicOffset);
vkCmdDraw(commandBuffers[i], m.vertexCount[j], 1, vertexCount, 0);
vertexCount += m.vertexCount[j];
}
- 使用 (n) 个描述符集用于 (n) 个模型,每个描述符集有两个绑定(一个用于UBO & 一个用于纹理采样器),在记录命令缓冲区的过程中,您只需绑定与要绘制的指定顶点属性对应的描述符集
优点:现在每个模型都有自己的 UBO 和纹理
缺点:效率低下
绘制过程
for (uint32_t j = 0; j < m.geometryCount; j++)
{
VkDescriptorSet finalSet = descriptorSet[j];
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &finalSet , 0, nullptr);
vkCmdDraw(commandBuffers[i], m.vertexCount[j], 1, vertexCount, 0);
vertexCount += m.vertexCount[j];
}
还有另一种方法涉及使用推送常量,在这种方法中,您将所有模型的 UBO 数据排列到一个数组中,然后从顶点着色器定义中为该 UBO 数组创建并绑定一个描述符集传入 UBO 数据的数组变量,然后在绘图操作期间使用推送常量发送单独的数组索引。但是我还没有测试过这个方法。
我想绘制一个包含多个对象的场景,每个对象都有自己的统一缓冲区和纹理,目前我可以使用动态统一缓冲区绘制多个对象,我这样做的方式是遍历动态统一缓冲区命令缓冲区记录期间的对象偏移和顶点索引,这样我告诉 Vulkan 使用特定的全局矩阵绘制模型,但是我不知道如何在此操作期间绑定纹理信息,以便 Vulkan 知道使用正确的该对象的纹理,在我的示例中,我有四个具有四种不同纹理的框。
您可以使用vkCmdBindDescriptorSets 绑定新纹理。
确保使用纹理绑定的描述符集是布局中编号最高的集。
当您使用 firstset > 0 调用 vkCmdBindDescriptorSets 时,绑定描述符集索引 [0 ... firstSet-1]
将保持不变。
到目前为止,我设法使用以下方法绘制了多个对象:-
注意:所有模型的所有顶点属性信息都存储在一个缓冲区中,该缓冲区是按模型组织的。
1.using 一个描述符集有两个绑定(一个用于 UBO,一个用于纹理采样器),UBO 的类型是动态的,以适应所有对象的 UBO,在命令缓冲区记录过程中,您只需遍历要绘制的指定顶点属性对应的Dynamic UBO数组
优点:高效快速
缺点:所有对象将具有相同的纹理(适用于多次渲染相同的模型,每次使用不同的ubo)
绘制过程
for (uint32_t j = 0; j < m.geometryCount; j++)
{
uint32_t dynamicOffset = j * 256;
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 1, &dynamicOffset);
vkCmdDraw(commandBuffers[i], m.vertexCount[j], 1, vertexCount, 0);
vertexCount += m.vertexCount[j];
}
- 使用 (n) 个描述符集用于 (n) 个模型,每个描述符集有两个绑定(一个用于UBO & 一个用于纹理采样器),在记录命令缓冲区的过程中,您只需绑定与要绘制的指定顶点属性对应的描述符集
优点:现在每个模型都有自己的 UBO 和纹理
缺点:效率低下
绘制过程
for (uint32_t j = 0; j < m.geometryCount; j++)
{
VkDescriptorSet finalSet = descriptorSet[j];
vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &finalSet , 0, nullptr);
vkCmdDraw(commandBuffers[i], m.vertexCount[j], 1, vertexCount, 0);
vertexCount += m.vertexCount[j];
}
还有另一种方法涉及使用推送常量,在这种方法中,您将所有模型的 UBO 数据排列到一个数组中,然后从顶点着色器定义中为该 UBO 数组创建并绑定一个描述符集传入 UBO 数据的数组变量,然后在绘图操作期间使用推送常量发送单独的数组索引。但是我还没有测试过这个方法。