在 OpenGL 中,是否保证几何着色器将按原始顺序接收图元内的顶点?
In OpenGL is it guaranteed that a geometry shader will receive vertices within a primitive in their original order?
例如,如果 glDraw* 调用绘图 GL_TRIANGLES 读取一组按顺序指定顶点 A、B、C、D、E 和 F 的 VBO,那么人们会期望在一个调用几何着色器,以下为真:
- gl_in[0] 描述 A
- gl_in[1]描述B
- gl_in[2]描述C
人们会期望在另一个调用中,以下内容为真:
- gl_in[0] 描述 D
- gl_in[1] 描述 E
- gl_in[2]描述F
等等。
但我发现在我找到的任何文档中都没有明确保证这一点。我想如果顶点被 OpenGL 以改变它们 CW/CCW 顺序的方式任意重新排序,那么很多人的正常查找代码(和其他类似的东西)可能会失败。但也许会允许这样的事情,例如:
- gl_in[0]描述B
- gl_in[1]描述C
- gl_in[2] 描述 A
OpenGL 可以重新排序吗?还是保证不会?
我这里用的是OpenGL 4.5 core profile specification,不过我说的基本上对早期版本也是正确的。确切的措辞(和声明的位置)可能与早期版本不同(尤其是在 4.3 之前,因为规范在该版本中完全重新组织)。
来自第 2.1 节 "Execution Model"(我的重点):
Primitives are defined by a group of one or more vertices. A vertex
defines a point, an endpoint of a line segment, or a corner of a
polygon where two edges meet. Data such as positional coordinates,
colors, normals, texture coordinates, etc. are associated with a
vertex and each vertex is processed independently, in order, and in
the same way. The only exception to this rule is if the group of
vertices must be clipped so that the indicated primitive fits within a
specified region; in this case vertex data may be modified and new
vertices created. The type of clipping
这基本上已经保证了它不能重新排序顶点。但是,我们可以为此找到更具体的语言。现在让我们集中讨论三角形的例子。第 10.1.8 节 "Separate Triangles" 指出
Separate triangles are specified with mode TRIANGLES
. In this case,
the 3i + 1st, 3i + 2nd, and 3i + 3rd vertices (in that order)
determine a triangle for each i = 0; 1;...; n - 1, where there
are 3n + k vertices drawn. k is either 0, 1, or 2; if k is not zero,
the final k vertices are ignored. For each triangle, vertex A is
vertex 3i and vertex B is vertex 3i + 1. Otherwise, separate triangles
are the same as a triangle strip.
那么三角形的顶点顺序是什么就一目了然了。因此,让我们在第 11.3 节中介绍几何着色器:
After vertices are processed, they are arranged into primitives, as
described in section
10.1.
上面定义的顺序在这里是完全相关的。现在是第 11.3.1 节中关于三角形的部分 "Geometry Shader Input Primitives":
Triangles (triangles)
Geometry shaders that operate on triangles are
valid for the TRIANGLES
, TRIANGLE_STRIP
and TRIANGLE_FAN
primitive
types. There are three vertices available for each program invocation.
The first, second and third vertices refer to attributes of the first,
second and third vertex of the triangle, respectively.
这与第 10.1.8 节中的引述一起清楚地表明,绘制调用的确切顺序保证出现在每个几何着色器调用中。
但是,不同几何着色器的调用顺序当然是未定义的,如7.12.1节所述"Shader Memory Access Ordering":
The relative order of invocations of the same shader type are
undefined. A store issued by a shader when working on primitive B
might complete prior to a store for primitive A, even if primitive A
is specified prior to primitive B. This applies even to fragment
shaders; while fragment shader outputs are always written to the
framebuffer in primitive order, stores executed by fragment shader
invocations are not.
但这无论如何都是并行架构所期望的,所以这里没有惊喜。
例如,如果 glDraw* 调用绘图 GL_TRIANGLES 读取一组按顺序指定顶点 A、B、C、D、E 和 F 的 VBO,那么人们会期望在一个调用几何着色器,以下为真:
- gl_in[0] 描述 A
- gl_in[1]描述B
- gl_in[2]描述C
人们会期望在另一个调用中,以下内容为真:
- gl_in[0] 描述 D
- gl_in[1] 描述 E
- gl_in[2]描述F
等等。
但我发现在我找到的任何文档中都没有明确保证这一点。我想如果顶点被 OpenGL 以改变它们 CW/CCW 顺序的方式任意重新排序,那么很多人的正常查找代码(和其他类似的东西)可能会失败。但也许会允许这样的事情,例如:
- gl_in[0]描述B
- gl_in[1]描述C
- gl_in[2] 描述 A
OpenGL 可以重新排序吗?还是保证不会?
我这里用的是OpenGL 4.5 core profile specification,不过我说的基本上对早期版本也是正确的。确切的措辞(和声明的位置)可能与早期版本不同(尤其是在 4.3 之前,因为规范在该版本中完全重新组织)。
来自第 2.1 节 "Execution Model"(我的重点):
Primitives are defined by a group of one or more vertices. A vertex defines a point, an endpoint of a line segment, or a corner of a polygon where two edges meet. Data such as positional coordinates, colors, normals, texture coordinates, etc. are associated with a vertex and each vertex is processed independently, in order, and in the same way. The only exception to this rule is if the group of vertices must be clipped so that the indicated primitive fits within a specified region; in this case vertex data may be modified and new vertices created. The type of clipping
这基本上已经保证了它不能重新排序顶点。但是,我们可以为此找到更具体的语言。现在让我们集中讨论三角形的例子。第 10.1.8 节 "Separate Triangles" 指出
Separate triangles are specified with mode
TRIANGLES
. In this case, the 3i + 1st, 3i + 2nd, and 3i + 3rd vertices (in that order) determine a triangle for each i = 0; 1;...; n - 1, where there are 3n + k vertices drawn. k is either 0, 1, or 2; if k is not zero, the final k vertices are ignored. For each triangle, vertex A is vertex 3i and vertex B is vertex 3i + 1. Otherwise, separate triangles are the same as a triangle strip.
那么三角形的顶点顺序是什么就一目了然了。因此,让我们在第 11.3 节中介绍几何着色器:
After vertices are processed, they are arranged into primitives, as described in section 10.1.
上面定义的顺序在这里是完全相关的。现在是第 11.3.1 节中关于三角形的部分 "Geometry Shader Input Primitives":
Triangles (triangles)
Geometry shaders that operate on triangles are valid for the
TRIANGLES
,TRIANGLE_STRIP
andTRIANGLE_FAN
primitive types. There are three vertices available for each program invocation. The first, second and third vertices refer to attributes of the first, second and third vertex of the triangle, respectively.
这与第 10.1.8 节中的引述一起清楚地表明,绘制调用的确切顺序保证出现在每个几何着色器调用中。
但是,不同几何着色器的调用顺序当然是未定义的,如7.12.1节所述"Shader Memory Access Ordering":
The relative order of invocations of the same shader type are undefined. A store issued by a shader when working on primitive B might complete prior to a store for primitive A, even if primitive A is specified prior to primitive B. This applies even to fragment shaders; while fragment shader outputs are always written to the framebuffer in primitive order, stores executed by fragment shader invocations are not.
但这无论如何都是并行架构所期望的,所以这里没有惊喜。