是否可以使用独特的几何着色器绘制带有线束的球体?

时间:2013-11-05 14:58:33

标签: opengl glsl shader geometry-shader

我想显示一个简单的UV球体(从Blender导出),并使用唯一的几何着色器生成具有法线坐标的线条。

我第一次编写了一个简单的几何着色器,它只是将输入顶点信息返回到片段着色器。为了简单起见(例如),我删除了片段着色器中的光度计算。

顶点着色器:

#version 400

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;

uniform mat4 MVP;

out vec3 VPosition;
out vec3 VNormal;

void main(void)
{
    VNormal = VertexNormal;
    gl_Position = vec4(VertexPosition, 1.0f);   
}

几何着色器:

#version 400

layout(points) in;
layout(line_strip, max_vertices = 2) out;

uniform mat4 MVP;

in vec3 VNormal[];

out vec3 fcolor;

void main(void)
{
    float size = 2.5f;

    fcolor = vec3(0.0f, 0.0f, 1.0f);
    gl_Position = MVP * gl_in[0].gl_Position;
    EmitVertex();

    fcolor = vec3(1.0f, 1.0f, 0.0f);
    gl_Position = MVP * vec4(gl_in[0].gl_Position.xyz + vec3(
        VNormal[0].x * size, VNormal[0].y * size, VNormal[0].z * size), 1.0f);
    EmitVertex();

    EndPrimitive();
}

片段着色器:

#version 400

in vec3 Position;
in vec3 Normal;
in vec2 TexCoords;

out vec4 FragColor;

in vec3 fcolor;

void main(void)
{
    FragColor = vec4(fcolor, 1.0f);
}

现在在C ++代码中绘制的基本类型(这里是三角形):

glDrawArrays(GL_TRIANGLES, 0, meshList[idx]->getVertexBuffer()->getBufferSize());

最后输出:

enter image description here

直到这里一切都好。 现在我想在球体上生成股线作为法线。为了完成工作,我编写了以下几何着色器(顶点和片段着色器是相同的)。

#version 400

layout(points) in;
layout(line_strip, max_vertices = 2) out;

uniform mat4 MVP;

in vec3 VNormal[];

out vec3 fcolor;

void main(void)
{
    float size = 1.0f;

    fcolor = vec3(0.0f, 0.0f, 1.0f);
    gl_Position = MVP * gl_in[0].gl_Position;
    EmitVertex();

    fcolor = vec3(1.0f, 1.0f, 0.0f);
    gl_Position = MVP * vec4(gl_in[0].gl_Position.xyz + vec3(
        VNormal[0].x * size, VNormal[0].y * size, VNormal[0].z * size), 1.0f);
    EmitVertex();

    EndPrimitive();
}

输入基元类型是我修改C ++代码以绘制场景的点:

glDrawArrays(GL_POINTS, 0, meshList[idx]->getVertexBuffer()->getBufferSize());

输出:

enter image description here

最后,如果我想在几何着色器中将三角形输入作为输入基元并将line_strip作为输出基元,我将使用以下着色器:

#version 400

layout(triangles, invocations = 3) in;
layout(line_strip, max_vertices = 6) out;

uniform mat4 MVP;

in vec3 VNormal[];

out vec3 fcolor;

void main(void)
{
    float size = 1.0f;

    for (int i = 0; i < 3; i++)
    {
        fcolor = vec3(0.0f, 0.0f, 1.0f);
        gl_Position = MVP * gl_in[i].gl_Position;
        EmitVertex();

        fcolor = vec3(1.0f, 1.0f, 0.0f);
        gl_Position = MVP * vec4(gl_in[0].gl_Position.xyz + vec3(
        VNormal[0].x * size, VNormal[0].y * size, VNormal[0].z * size), 1.0f);
        EmitVertex();

            EndPrimitive();
    }
}

输出如下:

enter image description here

但我的目标是使用相同的几何着色器在一个输出中显示场景(球体+线)。我想知道是否可以这样做。我不这么认为,因为几何着色器必须只有一种输入基元而另一种输出基本而不是几种类型。我想确定它是否可能。

1 个答案:

答案 0 :(得分:0)

谁知道,也许有一天会有一个扩展来从几何着色器中发出多个基本类型,但正如你所说,它目前无法完成。

另一种选择可能是用三角形绘制法线。

另一种,但在这种情况下完全无用,可能是使用变换反馈扩展来保存顶点着色器结果并使用两个单独的几何着色器重用该数据。我只提到这个,因为它是我能想到的最接近顶点阶段后发出多个基本类型的东西。

修改
<击> 绘制法线的两个几何着色器让我感到困惑。在第二个中,max_vertices = 3对于3个单独的行应该是6EndPrimitive也应该在for循环中,因此3个行没有连接。但是你已经通过在前一个中绘制GL_POINTS来对其进行排序。这是否适用于多个原始输出,如果它受支持?(已修复)

鉴于您的几何体重用了许多顶点,使用glDrawElements的索引会更有效。虽然您仍然希望使用glDrawArrays绘制法线,以避免绘制索引数组引用的重复顶点。