advanced rendering techniques

[TOC]

说明

内容

  • Drawing a skybox
  • Drawing billboards using geometry shaders
  • Drawing particles using compute and graphics pipelines
  • Rendering a tessellated terrain
  • Rendering a full-screen quad for post-processing
  • Using input attachments for a color correction post-process effect

介绍

order:right,left,up,down,backward,forward

vertex

1
2
3
4
5
6
7
8
9
10
11
12

layout( location = 0 ) in vec4 app_position;
layout( set = 0, binding = 0 ) uniform UniformBuffer {
mat4 ModelViewMatrix;
mat4 ProjectionMatrix;
};
layout( location = 0 ) out vec3 vert_texcoord;
void () {
vec3 position = mat3(ModelViewMatrix) * app_position.xyz;
gl_Position = (ProjectionMatrix * vec4( position, 0.0 )).xyzz;
vert_texcoord = app_position.xyz;
}

fragment

1
2
3
4
5
6
7

layout( location = 0 ) in vec3 vert_texcoord;
layout( set = 0, binding = 1 ) uniform samplerCube Cubemap;
layout( location = 0 ) out vec4 frag_color;
void () {
frag_color = texture( Cubemap, vert_texcoord );
}

Drawing billboards using geometry shaders

geometry shader

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

layout( points ) in;
layout( set = 0, binding = 0 ) uniform UniformBuffer {
mat4 ModelViewMatrix;
mat4 ProjectionMatrix;
};
layout( triangle_strip, max_vertices = 4 ) out;
layout( location = 0 ) out vec2 geom_texcoord;
const float SIZE = 0.1;
void () {
vec4 position = gl_in[0].gl_Position;
gl_Position = ProjectionMatrix * (gl_in[0].gl_Position + vec4(
-SIZE, SIZE, 0.0, 0.0 ));
geom_texcoord = vec2( -1.0, 1.0 );
EmitVertex();
gl_Position = ProjectionMatrix * (gl_in[0].gl_Position + vec4(
-SIZE, -SIZE, 0.0, 0.0 ));
geom_texcoord = vec2( -1.0, -1.0 );
EmitVertex();
gl_Position = ProjectionMatrix * (gl_in[0].gl_Position + vec4(
SIZE, SIZE, 0.0, 0.0 ));
geom_texcoord = vec2( 1.0, 1.0 );
EmitVertex();
gl_Position = ProjectionMatrix * (gl_in[0].gl_Position + vec4(
SIZE, -SIZE, 0.0, 0.0 ));
geom_texcoord = vec2( 1.0, -1.0 );
EmitVertex();
EndPrimitive();
}

Drawing particles using compute and graphics pipelines

Rendering a tessellated terrain

vertex

1
2
3
4
5
6
7
8

layout( location = 0 ) in vec4 app_position;
layout( location = 1 ) in vec2 app_texcoord;
layout( location = 0 ) out vec2 vert_texcoord;
void () {
gl_Position = app_position;
vert_texcoord = app_texcoord;
}

tessellation control

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

layout( location = 0 ) in vec2 vert_texcoord[];
layout( set = 0, binding = 0 ) uniform UniformBuffer {
mat4 ModelViewMatrix;
mat4 ProjectionMatrix;
};
layout( set = 0, binding = 1 ) uniform sampler2D ImageSampler;
layout( vertices = 3 ) out;
layout( location = 0 ) out vec2 tesc_texcoord[];
void () {
if( 0 == gl_InvocationID ) {
float distances[3];
float factors[3];
for( int i = 0; i < 3; ++i ) {
float height = texture( ImageSampler, vert_texcoord[i]
).x;
vec4 position = ModelViewMatrix * (gl_in[i].gl_Position +
vec4( 0.0, height, 0.0, 0.0 ));
distances[i] = dot( position, position );
}
factors[0] = min( distances[1], distances[2] );
factors[1] = min( distances[2], distances[0] );
factors[2] = min( distances[0], distances[1] );
gl_TessLevelInner[0] = max( 1.0, 20.0 - factors[0] );
gl_TessLevelOuter[0] = max( 1.0, 20.0 - factors[0] );
gl_TessLevelOuter[1] = max( 1.0, 20.0 - factors[1] );
gl_TessLevelOuter[2] = max( 1.0, 20.0 - factors[2] );
}
gl_out[gl_InvocationID].gl_Position =
gl_in[gl_InvocationID].gl_Position;
tesc_texcoord[gl_InvocationID] =
vert_texcoord[gl_InvocationID];
}

tessellation evaluation shader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#version 450
layout( triangles, fractional_even_spacing, cw ) in;
layout( location = 0 ) in vec2 tesc_texcoord[];
layout( set = 0, binding = 1 ) uniform sampler2D HeightMap;
layout( location = 0 ) out float tese_height;
void main() {
vec4 position = gl_in[0].gl_Position * gl_TessCoord.x +
gl_in[1].gl_Position * gl_TessCoord.y +
gl_in[2].gl_Position * gl_TessCoord.z;
vec2 texcoord = tesc_texcoord[0] * gl_TessCoord.x +
tesc_texcoord[1] * gl_TessCoord.y +
tesc_texcoord[2] * gl_TessCoord.z;
float height = texture( HeightMap, texcoord ).x;
position.y += height;
gl_Position = position;
tese_height = height;
}

geometry shader

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
#version 450
layout( triangles ) in;
layout( location = 0 ) in float tese_height[];
layout( set = 0, binding = 0 ) uniform UniformBuffer {
mat4 ModelViewMatrix;
mat4 ProjectionMatrix;
};
layout( triangle_strip, max_vertices = 3 ) out;
layout( location = 0 ) out vec3 geom_normal;
layout( location = 1 ) out float geom_height;
void main() {
vec3 v0v1 = gl_in[1].gl_Position.xyz -
gl_in[0].gl_Position.xyz;
vec3 v0v2 = gl_in[2].gl_Position.xyz -
gl_in[0].gl_Position.xyz;
vec3 normal = normalize( cross( v0v1, v0v2 ) );
for( int vertex = 0; vertex < 3; ++vertex ) {
gl_Position = ProjectionMatrix * ModelViewMatrix *
gl_in[vertex].gl_Position;
geom_height = tese_height[vertex];
geom_normal = normal;
EmitVertex();
}
EndPrimitive();
}

fragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#version 450
layout( location = 0 ) in vec3 geom_normal;
layout( location = 1 ) in float geom_height;
layout( location = 0 ) out vec4 frag_color;
void main() {
const vec4 green = vec4( 0.2, 0.5, 0.1, 1.0 );
const vec4 brown = vec4( 0.6, 0.5, 0.3, 1.0 );
const vec4 white = vec4( 1.0 );
vec4 color = mix( green, brown, smoothstep( 0.0, 0.4,
geom_height ) );
color = mix( color, white, smoothstep( 0.6, 0.9, geom_height )
);
float diffuse_light = max( 0.0, dot( geom_normal, vec3( 0.58,
0.58, 0.58 ) ) );
frag_color = vec4( 0.05, 0.05, 0.0, 0.0 ) + diffuse_light *
color;
}

full screen

input attachments for color correction post-process effect