GLSL Core Tutorial – Geometry Shader

原文:http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/geometry-shader/

 

  几何shader是OpenGL3.2之后的内容.这个阶段是可选的,当使用时,它接受在上一阶段组合的图元作为输入。一个几何shader不接受条带状,伞状或者环状的图元。几何shader接受组合后的图元,所以如何绘制命令指明是三角形带图元的话,几何shader实际上接受的是三角形。

    跟顶点shader比较,几何shader完全知道正在工作的图元。对于每一个输入图元,几何shader获取所以组成图元的顶点,如果指定的话,还包括邻接的信息。

几何shader可以接受的图元包括:

 

points (1)
lines (2)
lines_adjacency (4)
triangles (3)
triangles_adjacency (6)

括号里面的数字表示每种图元的顶点数量。

需要注意的是,几何shader的输入必须与在图元装配阶段描述图元匹配,那个阶段的图元由OpenGL绘制命令指出。当接受的图元带有邻接信息时(lines_adjacency 或者 triangles_adjacency)顶点的顺序如下所示:

 

输出图元类型有:

points
line_strip
triangle_strip

      输入输出之间的图元并不需要相互匹配。例如,几何shader接受三角形,输出则是点或者线条带。

一个几何shader可以输出0个或者更多的图元。例如,if outputting triangle strips, a geometry shader can output three strips, with two triangles each。在shader处理之后,输入图元通常被丢弃。

      这意味着,如果几何shader选择不为特定的输入图元生成任何输出图元的话,等效于一些剔除处理。同样,对于每一个图元,几何shader可以生成多个图元。然而要注意的是,几何shader不是被设计去生成大量几何图形的,例如,它不能够担任细分的目的。

     输入和输出图元的类型都需要在shader中使用layout说明符进行声明。假设输入图元类型是三角形,输出图元类型是线条,我们的shader代码可以像下面这样:

// geometry shaders require at least version 1.5
#version 150
 
layout (triangles) in;
layout (line_strip, max_vertices = 4) out;
...

        max_vertices限制着几何shadr输出的顶点数量,这是真的!惊讶如果我们尝试输出比说明更多的顶点,超过的顶点将不会送到 Pipeline的保留区。在OpenGL4.0, 对于每一个输入图元,一个几何shader能够被调用多次。在输入layout说明符中的invocations定义了调用次数的值。在下面的例子中,每一个图元几何shader要被调用两次。

#version 400
 
layout (triangles, invocations = 2) in;
layout (line_strip, max_vertices = 4) out;
...

     如果在layout中invocations是缺省的话,每一个图元shader会调用一次。

除了用户定义的那些作为顶点shader输出的顶点属性外,几何shader可以获取unifrom变量和纹理值。

下面是提供的内置变量:

in gl_PerVertex {
    vec4  gl_Position;
    float gl_PointSize;
    float gl_ClipDistance[];
} gl_in[];

in int gl_PrimitiveIDIn;
// only for OpenGL 4.0+
in int gl_InvocationID;

      需要注意的是,几何shader输入的in结构体gl_PerVertex必须与顶点shader里面out结构体对应相等,但这一次是以数组的格式。gl_PrimitiveID变量存储着OpenGL的Draw命令生成的图元索引值。

      尽管在概念上几何shader生成图元,事实上它生成的是顶点。因此,如果输出图元是一个三角形的话,几何shader应该写入三个顶点的属性值。然后顶点根据输出layout的设置组合成图元。对于每个顶点有着下列的内置变量可以使用:

out gl_PerVertex {
    vec4  gl_Position;
    float gl_PointSize;
    float gl_ClipDistance[];
};

out int gl_PrimitiveID;
out int gl_Layer;
// only for OpenGL 4.1+
out int gl_ViewportIndex;

        在顶点shader中,gl_Position是可选的,但是接下来的阶段可能依赖它来进行插值操作。对于每个provoking的顶点,gl_PrimitiveID至少应该被写入一次。至于gl_Layer和gl_ViewportIndex, 如果说明的话,一个图元的所有顶点必须被写入相同的值。没有说明的话,例如:如果几何shader没有写入gl_ViewportIndex或者gl_Layer, 那么他们的值将会是0.

        在绘制时,几何shader的每一个图元可以被指定一个layer。This allows the geometry shader to specify multiple primitives, and direct them to different layers. Layered rendering 说明帧缓存的使用方式,反之gl_Layer被忽略。层次rendering的一个使用例子是:一次传递,映射到一个立方体的六个面。

      在OpenGL4.1,几何shader可以选择输出ViewPort,使用这个特性多视图可以同时进行rendering。

除了内置变量,几何shader可以声明并写入用户定义的变量。正如前面的shader,使用变换的反馈,几何着色器的输出可以被重定向到一个缓冲器(或一组缓冲器。

posted @ 2014-12-07 19:06  byhj  阅读(793)  评论(0编辑  收藏  举报