Browse code

Add implementation

Robert Cranston authored on 20/12/2021 13:03:47
Showing 5 changed files

... ...
@@ -2,11 +2,123 @@
2 2
 
3 3
 A [GLSL][]/[OpenGL][] [\>=3.2][] [quad][] library.
4 4
 
5
+The main functionality is [generation][] of (2D or 3D) quads with the provided
6
+[vertex shader][] and [geometry shader][], expected to be used with a custom
7
+[fragment shader][].
8
+
9
+Mostly as a convenience, [fragment shader][]s are provided for [drawing][] (2D
10
+or 3D) textures.
11
+
12
+Other libraries, interoperating well with this one, that may be of interest:
13
+
14
+-   [`glshader`][], easing the use of [shader][]s.
15
+-   [`glframebuffer`][], easing the use of [framebuffer object][]s.
16
+-   [`glconventions`][], documenting the conventions used.
17
+
5 18
 [`glquad`]: https://git.rcrnstn.net/rcrnstn/glquad
6 19
 [GLSL]: https://en.wikipedia.org/wiki/OpenGL_Shading_Language
7 20
 [OpenGL]: https://en.wikipedia.org/wiki/OpenGL
8 21
 [\>=3.2]: https://en.wikipedia.org/wiki/OpenGL#Version_history
9 22
 [quad]: https://en.wikipedia.org/wiki/Quadrilateral
23
+[generation]: #generation
24
+[vertex shader]: https://www.khronos.org/opengl/wiki/Vertex_Shader
25
+[geometry shader]: https://www.khronos.org/opengl/wiki/Geometry_Shader
26
+[fragment shader]: https://www.khronos.org/opengl/wiki/Fragment_Shader
27
+[drawing]: #drawing
28
+[`glshader`]: https://git.rcrnstn.net/rcrnstn/glshader
29
+[shader]: https://www.khronos.org/opengl/wiki/Shader
30
+[`glframebuffer`]: https://git.rcrnstn.net/rcrnstn/glframebuffer
31
+[framebuffer object]: https://www.khronos.org/opengl/wiki/Framebuffer_Object
32
+[`glconventions`]: https://git.rcrnstn.net/rcrnstn/glconventions
33
+
34
+## Requirements
35
+
36
+[Geometry shader][]s require OpenGL [\>=3.2][] or the
37
+[`ARB_geometry_shader4`][] extension.
38
+
39
+[`ARB_geometry_shader4`]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_geometry_shader4.txt
40
+
41
+## Usage
42
+
43
+Link the shader program with:
44
+
45
+-   `quad.vert`
46
+-   `quad.geom`
47
+
48
+The following uniforms need to be set:
49
+
50
+-   `int instance_count`
51
+
52
+The following outputs are written by the [geometry shader][]:
53
+
54
+-   `vec3 position`, in the range `-1` to `+1`
55
+-   `vec2 tex_coord`, in the range `0` to `1`
56
+
57
+When issuing the draw call, use the following for 2D:
58
+
59
+```
60
+glDrawArrays(GL_POINTS, 0, 1);
61
+```
62
+
63
+and the following for 3D:
64
+
65
+```
66
+glDrawArraysInstanced(GL_POINTS, 0, 1 instance_count);
67
+```
68
+
69
+Here, `instance_count` is the number of [layer][]s in the [framebuffer][]; `1`
70
+for 2D, texture depth for 3D.
71
+
72
+[layer]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Layered_rendering
73
+[framebuffer]: https://www.khronos.org/opengl/wiki/Framebuffer
74
+
75
+### Generation
76
+
77
+Vertices are generated entirely within a [geometry shader][], so no vertex
78
+state (except for the obligatory [vertex array object][] for OpenGL [\>=3.3][])
79
+has to be set up on the CPU (no data is even read by the [vertex shader][]),
80
+potentially making operation transparent to other code, which can leave their
81
+state bound.
82
+
83
+[Instanced rendering][], with each instance rendering to a separate [layer][],
84
+is used since it enables a large, dynamic, number of layers. [Geometry shader
85
+instancing][] is more self-contained and requires less work by the CPU (simply
86
+`glDrawArrays`), but is limited to a fixed, small, number of layers, and
87
+requires OpenGL [\>=4.0][] or the [`ARB_gpu_shader5`][] extension.
88
+
89
+[vertex array object]: https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object
90
+[\>=3.3]: https://en.wikipedia.org/wiki/OpenGL#Version_history
91
+[instanced rendering]: https://www.khronos.org/opengl/wiki/Vertex_Rendering#Instancing
92
+[geometry shader instancing]: https://www.khronos.org/opengl/wiki/Geometry_Shader#Instancing
93
+[\>=4.0]: https://en.wikipedia.org/wiki/OpenGL#Version_history
94
+[`ARB_gpu_shader5`]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_gpu_shader5.txt
95
+
96
+### Drawing
97
+
98
+The following outputs are written by these fragment shaders:
99
+
100
+-   ` vec4 frag_color`
101
+
102
+#### 2D
103
+
104
+Link the shader program with:
105
+
106
+-   `quad2d.frag`
107
+
108
+The following uniforms need to be set:
109
+
110
+-   `sampler2D texture0`
111
+
112
+#### 3D
113
+
114
+Link the shader program with:
115
+
116
+-   `quad3d.frag`
117
+
118
+The following uniforms need to be set:
119
+
120
+-   `sampler3D texture0`
121
+-   `float tex_coord_z`, `z` coordinate with which to sample `texture0`
10 122
 
11 123
 ## Build system
12 124
 
13 125
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+#version 150
2
+
3
+
4
+uniform int instance_count;
5
+
6
+
7
+layout(points) in;
8
+layout(triangle_strip, max_vertices = 4) out;
9
+
10
+
11
+in int instance_id[];
12
+
13
+
14
+out vec3 position;
15
+out vec2 tex_coord;
16
+
17
+
18
+void quad_vertex_(vec3 pos, int layer)
19
+{
20
+    position       = pos;
21
+    tex_coord      = pos.xy * 0.5 + 0.5;
22
+    gl_Position    = vec4(pos, 1);
23
+    gl_Layer       = layer;
24
+    gl_PrimitiveID = gl_PrimitiveIDIn;
25
+    EmitVertex();
26
+}
27
+
28
+
29
+void main()
30
+{
31
+    float z = (instance_id[0] + 0.5) / instance_count * 2 - 1;
32
+    quad_vertex_(vec3(-1, -1, z), instance_id[0]);
33
+    quad_vertex_(vec3(-1, +1, z), instance_id[0]);
34
+    quad_vertex_(vec3(+1, -1, z), instance_id[0]);
35
+    quad_vertex_(vec3(+1, +1, z), instance_id[0]);
36
+    EndPrimitive();
37
+}
0 38
new file mode 100644
... ...
@@ -0,0 +1,10 @@
1
+#version 150
2
+
3
+
4
+out int instance_id;
5
+
6
+
7
+void main()
8
+{
9
+    instance_id = gl_InstanceID;
10
+}
0 11
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+#version 150
2
+
3
+
4
+uniform sampler2D texture0;
5
+
6
+
7
+in vec2 tex_coord;
8
+
9
+
10
+out vec4 frag_color;
11
+
12
+
13
+void main()
14
+{
15
+    frag_color = texture(texture0, tex_coord);
16
+}
0 17
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+#version 150
2
+
3
+
4
+uniform sampler3D texture0;
5
+uniform float tex_coord_z;
6
+
7
+
8
+in vec2 tex_coord;
9
+
10
+
11
+out vec4 frag_color;
12
+
13
+
14
+void main()
15
+{
16
+    frag_color = texture(texture0, vec3(tex_coord.xy, tex_coord_z));
17
+}