如何使用几何着色器创建坐标来绘制TRIANGLE_FAN? (GLSL 3.3)

时间:2015-02-24 19:49:10

标签: opengl opengl-3 geometry-shader

我想用GS绘制多个粉丝。每个风扇应该每次都向摄像机广告,这使得每个顶点必须与MVP矩阵相乘。 由于每个风扇都可由用户移动,我想出了为GS提供位置的想法。

以下几何着色器按预期工作,其中包含输入和输出:

uniform mat4 VP;
uniform mat4 sharedModelMatrix;

const int STATE_VERTEX_NUMBER = 38;

layout (shared) uniform stateShapeData {
    vec2 data[STATE_VERTEX_NUMBER];
};

layout (triangles) in;
layout (triangle_strip, max_vertices = 80) out;

void main(void)
{
    int i;
    mat4 modelMatrix = sharedModelMatrix;
    modelMatrix[3]   = gl_in[0].gl_Position;
    mat4 MVP = VP * modelMatrix;

    gl_Position = MVP * vec4( 0, 0 , 0, 1 );
    EmitVertex(); // epicenter

    for (i = 37; i >= 0; i--) {
        gl_Position = MVP * vec4( data[i], 0, 1 );
        EmitVertex();
     }

     gl_Position = MVP * vec4( data[0], 0, 1 );
     EmitVertex();
}

我尝试使用glDrawElementsglDrawArraysglMultiDrawArrays运行此功能。这些命令都没有绘制完整的风扇。每个绘制第一个填充的三角形,剩余的顶点绘制为点。

所以,最底层的问题是:是否可以使用GS创建的顶点绘制扇形?如何?

1 个答案:

答案 0 :(得分:2)

如您所发现的那样,在几何着色器中输出粉丝非常不自然。

您当前正在以扇形顺序输出顶点,这是一种在原始程序集之后对GPU 完全陌生的构造。风扇作为汇编器输入非常有用,但就输出而言,光栅化器只能理解条带的概念。

要正确编写此着色器,您需要将此扇形分解为一系列单独的三角形。这意味着您编写的循环实际上将在每次迭代时输出震中。

void main(void)
{
    int i;
    mat4 modelMatrix = sharedModelMatrix;
    modelMatrix[3]   = gl_in[0].gl_Position;
    mat4 MVP = VP * modelMatrix;

    for (i = 37; i >= 0; i--) {
        gl_Position = MVP * vec4( 0, 0 , 0, 1 );
        EmitVertex(); // epicenter

        gl_Position = MVP * vec4( data[i], 0, 1 );
        EmitVertex();

        gl_Position = MVP * vec4( data[i-1], 0, 1 );
        EmitVertex();

        // Fan and strip DNA just won't splice
        EndPrimitive ();
     }
}

以这种方式绘制时,您无法利用条带排序;你不得不多次结束输出原语(strip)。关于绘制扇形顺序的唯一可能的好处是循环内的缓存局部性。如果您了解几何着色器应该输出三角形条带,为什么不以这种方式开始命令您的输入顶点?