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

Mic*_*Wei 7 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(...);
Run Code Online (Sandbox Code Playgroud)

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

干杯

Nic*_*las 8

您有一个概念对象,它由多个网格组成,具有不同的纹理需求.解决这个问题的一般方法是:

  1. 更改对象各部分之间的描述符集.痛苦,但它适用于所有支持Vulkan的硬件.

  2. 使用数组纹理.每个单独的网格从数组纹理中的特定图层获取其数据.当然,这会限制您使每个子网格使用相同大小的纹理.但它适用于所有支持Vulkan的硬件(最多128个阵列元素).特定网格的数组层可以作为推送常量提供,或者如果可用则提供基础实例.

    请注意,如果您设法通过基本实例执行此操作,则可以使用多绘制间接命令呈现整个对象.虽然目前尚不清楚短抽取间接是否比仅将一小段绘图命令烘焙到命令缓冲区更快.

  3. 正如Sascha Willems所建议的那样,采用采样器阵列.据推测,子网格的数组索引被提供为推送常量或基本实例.问题在于,无论如何提供该数组索引,它都必须是动态统一的表达式.并且不要求 Vulkan实现允许您使用动态统一表达式索引采样器数组.基本要求只是一个常量表达式.

    这限制了您支持该shaderSampledImageArrayDynamicIndexing功能的硬件.所以你必须要求它,如果它不可用,那么你必须用#1或#2来解决这个问题.或者只是不要在该硬件上运行.但最后一个意味着您无法在任何移动硬件上运行,因为它们中的大多数尚不支持此功能.

    请注意,我并不是说你不应该使用这种方法.我只是想让你知道有成本.那里有很多硬件无法做到这一点.所以你需要为此做好计划.


Sas*_*ems 6

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

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

如果你看一下 NVIDIA 的斩波器示例,他们的做法几乎相同,只是做了一些更多的抽象。

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

VkDescriptorSet *textureDescriptors = m_renderer->getTextureDescriptorSets();
Run Code Online (Sandbox Code Playgroud)

几行后绑定它们:

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);
Run Code Online (Sandbox Code Playgroud)

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

vkCmdDrawIndexedIndirect(m_draw_command[inCommandIndex], sceneIndirectBuffer, 0, inCount, sizeof(VkDrawIndexedIndirectCommand));
vkCmdDraw(m_draw_command[inCommandIndex], 1, 1, 0, 0);
Run Code Online (Sandbox Code Playgroud)

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

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