在多个网格上的Vulkan纹理渲染

时间:2016-04-21 14:26:44

标签: texture-mapping texture2d vulkan

我正在模型的多个网格上渲染不同的纹理,但我没有太多关于这些过程的线索。有人为每个网格建议,创建自己的描述符集并调用vkCmdBindDescriptorSets()和vkCmdDrawIndexed()进行渲染,如下所示:

    // Pipeline with descriptor set layout that matches the shared descriptor sets
vkCmdBindPipeline(...pipelines.mesh...);
...
// Mesh A
vkCmdBindDescriptorSets(...&meshA.descriptorSet... );
vkCmdDrawIndexed(...);
// Mesh B
vkCmdBindDescriptorSets(...&meshB.descriptorSet... );
vkCmdDrawIndexed(...);

然而,上述方法与切碎机样本和vulkan的样本完全不同,这使得我不知道从哪里开始改变。我非常感谢任何帮助,指导我找到正确的方向。

干杯

2 个答案:

答案 0 :(得分:7)

You have a conceptual object which is made of multiple meshes which have different texturing needs. The general ways to deal with this are:

  1. Change descriptor sets between parts of the object. Painful, but it works on all Vulkan-capable hardware.

  2. Employ array textures. Each individual mesh fetches its data from a particular layer in the array texture. Of course, this restricts you to having each sub-mesh use textures of the same size. But it works on all Vulkan-capable hardware (up to 128 array elements, minimum). The array layer for a particular mesh can be provided as a push-constant, or a base instance if that's available.

    Note that if you manage to be able to do it by base instance, then you can render the entire object with a multi-draw indirect command. Though it's not clear that a short multi-draw indirect would be faster than just baking a short sequence of drawing commands into a command buffer.

  3. Employ sampler arrays, as Sascha Willems suggests. Presumably, the array index for the sub-mesh is provided as a push-constant or base instance. The problem is that, regardless of how that array index is provided, it will have to be a dynamically uniform expression. And Vulkan implementations are not required to allow you to index a sampler array with a dynamically uniform expression. The base requirement is just a constant expression.

    This limits you to hardware that supports the shaderSampledImageArrayDynamicIndexing feature. So you have to ask for that, and if it's not available, then you've got to work around that with #1 or #2. Or just don't run on that hardware. But the last one means that you can't run on any mobile hardware, since most of them don't support this feature as of yet.

    Note that I am not saying you shouldn't use this method. I just want you to be aware that there are costs. There's a lot of hardware out there that can't do this. So you need to plan for that.

答案 1 :(得分:4)

建议上面代码片段的人就是我,我猜;)

这只是一种方法。您不必为每个网格或每个纹理创建一个描述符集。如果您的网格例如使用4种不同的纹理,您可以将所有纹理一次绑定到不同的绑定点,并在着色器中选择它们。

如果你看一下NVIDIA的斩波器样本,他们只是采用更多的抽象方式来做同样的事情。

该示例还为使用的纹理设置了描述符集:

VkDescriptorSet *textureDescriptors = m_renderer->getTextureDescriptorSets();

稍后将它们绑定几行:

VkDescriptorSet sets[3] = { sceneDescriptor, textureDescriptors[0], m_transform_descriptor_set };
vkCmdBindDescriptorSets(m_draw_command[inCommandIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 3, sets, 0, NULL);

然后使用绑定的描述符集渲染网格:

vkCmdDrawIndexedIndirect(m_draw_command[inCommandIndex], sceneIndirectBuffer, 0, inCount, sizeof(VkDrawIndexedIndirectCommand));
vkCmdDraw(m_draw_command[inCommandIndex], 1, 1, 0, 0);

如果您查看 initDescriptorSets ,您会发现它们还为立方体贴图,地形等创建了单独的描述符集。

LunarG示例应该类似,但如果我没弄错,他们从不使用多个纹理?