哪种方法最好用Vulkan API实现粒子着色器?

问题描述 投票:0回答:1

我正在实现粒子着色器,它意味着绘制许多矩形,每个矩形都有唯一的数据。现在,我看到了执行此操作的不同方法。


方式1:

  1. 对所有粒子使用一个统一的缓冲区
  2. 在绘制开始时执行单个vkCmdBindDescriptorSets
  3. 调用实例计数等于粒子计数的单个vkCmdDraw
  4. 在顶点着色器中,使用仅由单个数组组成的统一结构:
struct Particle
{
    //...
};

layout(binding = 0) uniform ParticleUniformBufferObject
{
    Particle particles[MAX_PARTICLES_TO_DRAW];
} ubo;
  1. 然后在绘制时使用glsl变量访问统一数据
vec3 particlePosition = ubo.particles[gl_InstanceID].position;

方式2:

  1. 对所有粒子使用一个统一的缓冲区
  2. 使用动态偏移为每个粒子执行vkCmdBindDescriptorSets
  3. 对实例计数为1的每个粒子执行vkCmdDraw
  4. 以不带数组的常见方式访问顶点着色器中的缓冲数据

方式3:

通过顶点输入来执行所有操作,并且没有任何按对象的制服。可能会有很多不必要的数据开销。在这种情况下,应在每帧更新顶点缓冲区。


我的问题-哪种方式在效果上更好?

或者您是否看到使用Vulkan API进行粒子渲染的另一种好方法?

c++ vulkan particles particle-system
1个回答
0
投票

另一种方法是使用间接绘图:vkCmdDrawIndirect。如果您只能在GPU上修改粒子,则这种方法可能会有所回报。如果您需要动画/修改/等。将它们放在CPU上,那么间接绘图将无济于事。

就您的粒子数据而言,您将它们存储在vkCmdDrawIndirect缓冲区中,在计算着色器遍历中对其进行修改,并使用间接绘制调用对其进行渲染。要访问粒子的数据,必须使用VK_BUFFER_USAGE_STORAGE_BUFFER_BIT的内置GLSL


通常,在性能方面,无法分辨出哪种方法比另一种方法更好。这取决于许多因素:取决于如何修改粒子,粒子所依赖的粒子,粒子的数量,使用的GPU等。如果您真的想知道,则必须实施所有方法并进行测量。

如果要进行后者,请分享您的结果并描述您的设置!这样的东西总是很有趣。

© www.soinside.com 2019 - 2024. All rights reserved.