RealTime-Rendering21-Geometry Shader

Geometry Shader

in/out layout qualifier

几何着色器需要定义输入的图元以及输出的图元信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#version 460 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();
}

输入的图元可以使用以下任意一种类型:

  • points: when drawing GL_POINTS primitives (1).
  • lines: when drawing GL_LINES or GL_LINE_STRIP (2).
  • lines_adjacency: GL_LINES_ADJACENCY or GL_LINE_STRIP_ADJACENCY (4).
  • triangles: GL_TRIANGLES, GL_TRIANGLE_STRIP or GL_TRIANGLE_FAN (3).
  • triangles_adjacency : GL_TRIANGLES_ADJACENCY or GL_TRIANGLE_STRIP_ADJACENCY (6).

输出的图元仅可以使用以下三种类型:

  • points
  • line_strip
  • triangle_strip

几何着色器允许在渲染管线中动态的生成几何体。即使绘制命令只指定了最基础的图元(比如4个点),几何着色器也能将这些点实时扩展为更复杂的形状,从而用非常简单的输入创造出丰富的视觉效果。
glDrawArrays/glDrawElements中传入的图元类型对应了几何着色器中输入的图元类型(in)

Varyings

顶点着色器定义的输出变量,几何着色器需要用数组来接收

Examples

Explode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#version 460 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

in VS_OUT
{
vec2 texCoords;
} gs_in[];

out vec2 TexCoords;

uniform float time;

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);
}

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));
}

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();
}

Visualizing normal vectors

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//vertex Shader
#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out VS_OUT
{
vec3 normal;
} vs_out;

uniform mat4 view;
uniform mat4 model;

void main()
{
gl_Position = view * model * vec4(aPos, 1.0);
mat3 normalMatrix = mat3(transpose(inverse(view * model)));
vs_out.normal = normalize(vec3(vec4(normalMatrix * aNormal, 0.0)));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//geometry Shader
#version 460 core
layout (triangles) in;
layout (line_strip, max_vertices = 6) out;

in VS_OUT
{
vec3 normal;
} gs_in[];

const float MAGNITUDE = 0.4;

uniform mat4 projection;

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

void main()
{
GenerateLine(0); // first vertex normal
GenerateLine(1); // second vertex normal
GenerateLine(2); // third vertex normal
}