0

几何着色器的“调用”输入布局限定符有什么作用?

OpenGL wiki只是说它会导致 GS 对每个图元执行多次,然后继续说:

实例的输出原语按 gl_InvocationID 排序。因此,从 3 个实例写入的 2 个基元将创建一个基元流:(prim0, inst0), (prim0, inst1), (prim0, inst2), (prim1, inst0)

每次调用是否都对前一次调用的数据进行操作,例如迭代地优化几何?还是应该使用 gl_InvocationID 来在每次调用中执行不同的操作?还是我完全走错了路?

4

2 回答 2

2

它在着色器中实例化;它在庄园中的工作几乎与实例化等完全一样glDrawArraysInstanced。通过num_instances调用 GS 处理相同的输入原语。每个调用都是完全独立的,就像实例化渲染中的每个实例都是完全独立的一样。

对于相同的原始输入,区分一个 GS 调用和另一个调用之间的区别的唯一方法是使用gl_InvocationID. 对于同一原语中的每次调用,这将是不同的。

于 2013-06-05T10:01:20.040 回答
1

“调用”类似于实例化,但用途略有不同。

考虑调用:

glDrawArray(GL_POINTS, 0, N );

使用着色器布局:

 layout (points, invocations=6) in;

注意 OpenGL wiki 中给出的调用顺序:
(prim0, invoc0), (prim0, invoc1), (prim0, invoc2), (prim1, invoc0), ... (primN, invoc1), (primN, invoc2)

调用的目的是在开始下一个原语之前按顺序处理每个调用。有时你需要这个。然而,使用调用对于 GPU 来说代价很高,因为它们必须按顺序发生,并且不容易并行化。

您可以通过使用统一缓冲区来实现与顺序无关的调用。

 const int NUM_INVOC = 6;
   for (int i = 0; i < NUM_INVOC; ++i) {
       glUniform1i( glGetUniformLocation("uiInvocID"), i);
       glDrawArray( GL_POINTS, 0, N );
   }

然后,在 GS 中使用统一的 uiInvocID 而不是 gl_InvocationID。
其处理顺序将是:
(prim0, invoc0), (prim1, invoc0), (prim2, invoc0), (prim0, invoc1), (prim1, invoc1), (prim2, invoc1), ..

在许多情况下,顺序可能无关紧要。例如,如果您将一组点扩展为一个立方体,首先渲染所有顶面,然后渲染所有侧面等仍然完全可以接受,因为 Z 缓冲区将解决所有问题。这会快得多。

回想一下,实例化的作用是不同的:
(prim0, inst0), (prim1, inst1), (prim2, inst2) .. (primN, instN)

对于常规实例化,prims 和 gl_InstanceIDs 之间存在一对一的关系。

于 2014-08-06T23:26:43.517 回答