使用 Vulkan 中的纹理绘制多个对象

Bul*_*Bul 0 3d game-engine vulkan

我想绘制一个场景,其中包含多个对象,每个对象都有自己的统一缓冲区和纹理,目前我能够使用动态统一缓冲区绘制多个对象,我这样做的方法是遍历动态统一缓冲区对象偏移量和索引命令缓冲区记录期间的顶点,这样我告诉 Vulkan 使用特定的全局矩阵绘制模型,但是我不知道如何在此操作期间绑定纹理信息,以便 Vulkan 知道为该对象使用正确的纹理,在我的示例中,我有四个具有四种不同纹理的盒子。

rat*_*eak 5

您可以使用 vkCmdBindDescriptorSets 来绑定新纹理。

确保具有纹理绑定的描述符集是布局中编号最高的集。

当您使用firstset > 0调用vkCmdBindDescriptorSets时,绑定描述符集索引[0 ... firstSet-1]将保持不变。


Bul*_*Bul 5

到目前为止,我设法使用以下方法绘制了多个对象:-

注意:所有模型的所有顶点属性信息都存储在一个缓冲区中,该缓冲区以每个模型为基础进行组织。

1.使用一个带有两个绑定的描述符集(一个用于 UBO,一个用于纹理采样器),UBO 的类型是动态的,以适应所有对象的 UBO,在命令缓冲区记录过程中,您只需遍历对应的动态 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];
    }
Run Code Online (Sandbox Code Playgroud)
  1. 使用(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];
    }
Run Code Online (Sandbox Code Playgroud)

还有另一种方法涉及使用推送常量,在这种方法中,您将所有模型的 UBO 数据排列到一个数组中,然后为该 UBO 数组创建和绑定单个描述符集,从顶点着色器为传入的 UBO 数据,然后在绘图操作期间使用推送常量发送单个数组索引。但是我还没有测试过这个方法。