几何着色器

 

  一般我们只使用了顶点和片段着色器,这也是基本和必须的两个着色器,而几何着色器是一个可选的着色器,其位于顶点和片段着色器之间。

  几何着色器接收来自顶点着色器的一个片元的一组顶点,然后可以对其进行变换,可以输出新的不同类型的片元,也可以增加顶点数,其功能非常强大。

  一般写法如下:

#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 2) out;

void main() {    
    gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0); 
    EmitVertex();

    gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0);
    EmitVertex();

    EndPrimitive();
}

  可以看到首先定义了输入和输出布局修饰符。

  输入修饰符:

layout (points) in;

  括号中的输入片元类型一般应该与顶点着色器接收的顶点数据一致,有以下几种片元类型(后面的括号中的数字表示此片元包含的最少顶点数):

  • points:绘制GL_POINTS图元时(1)。
  • lines:绘制GL_LINESGL_LINE_STRIP时(2)
  • lines_adjacencyGL_LINES_ADJACENCYGL_LINE_STRIP_ADJACENCY(4)
  • trianglesGL_TRIANGLESGL_TRIANGLE_STRIPGL_TRIANGLE_FAN(3)
  • triangles_adjacencyGL_TRIANGLES_ADJACENCYGL_TRIANGLE_STRIP_ADJACENCY(6)

  输出修饰符:

layout (line_strip, max_vertices = 2) out;

  max_vertices=2 表示:对应顶点着色器输出的每个片元,几何着色器每次处理的最大顶点数量,超出的顶点就不再处理了。

  可供选择的输出修饰符有:

  • points
  • line_strip
  • triangle_strip

  

  效果展示:

  1、输入片元为points,渲染“房子”

#version 430 core
layout (points) in;
layout (triangle_strip, max_vertices=5) out;

in VS_OUT{
    vec3 color;
}gs_in[];

out vec3 fColor;

void build_Quad(vec4 p){
    fColor=gs_in[0].color;
    gl_Position=p+vec4(-0.2,-0.2, 0, 0);
    EmitVertex();
    gl_Position=p+vec4( 0.2,-0.2, 0, 0);
    EmitVertex();
    gl_Position=p+vec4(-0.2, 0.2, 0, 0);
    EmitVertex();
    gl_Position=p+vec4( 0.2, 0.2, 0, 0);
    EmitVertex();
    gl_Position=p+vec4( 0.0, 0.4, 0, 0);
    fColor=vec3(1.0,1.0,1.0);
    EmitVertex();
    EndPrimitive();
}

void main(){
    build_Quad(gl_in[0].gl_Position);
}

 

  2、nanosuit模型爆炸效果

#version 430 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

in VS_OUT{
    vec3 FragPos;
    vec2 TexCoords;
    vec3 Normal;
}gs_in[];

out vec2 TexCoords;

uniform float time;

vec3 GetNormal(){
    vec3 a=vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position);
    vec3 b=vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position);
    return normalize(cross(a,b));
}

vec4 explode(vec4 position, vec3 normal){
    float magnitude=2.0;
    vec3 direction=normal*((sin(time)+1.0)/2.0)*magnitude;
    return position+vec4(direction,0.0);
}

void main(){
    vec3 normal = GetNormal();

    gl_Position=explode(gl_in[0].gl_Position,normal);
    TexCoords=gs_in[0].TexCoords;
    EmitVertex();
    gl_Position=explode(gl_in[1].gl_Position,normal);
    TexCoords=gs_in[1].TexCoords;
    EmitVertex();
    gl_Position=explode(gl_in[2].gl_Position,normal);
    TexCoords=gs_in[2].TexCoords;
    EmitVertex();
    EndPrimitive();
}

 

  3、nanosuit模型的法线可视化

#version 430 core
layout (triangles) in;
layout (line_strip, max_vertices = 6) out;

in VS_OUT{
    vec3 FragPos;
    vec2 TexCoords;
    vec3 Normal;
}gs_in[];

void GenerateLine(int index){
    gl_Position=gl_in[index].gl_Position;
    EmitVertex();
    gl_Position=gl_in[index].gl_Position + vec4(gs_in[index].Normal,0.0) * 0.4;
    EmitVertex();
    EndPrimitive();
}

void main(){
    GenerateLine(0);
    GenerateLine(1);
    GenerateLine(2);
}

 

posted @ 2019-09-04 15:29 茶飘香~ 阅读(...) 评论(...) 编辑 收藏