1 /**
2 Copyright: Copyright (c) 2017-2018 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module voxelman.graphics.shaders;
8 
9 import voxelman.graphics.gl;
10 import voxelman.graphics.irenderer;
11 import voxelman.graphics.shaderprogram;
12 import voxelman.math;
13 
14 
15 string solid_frag_shader = `
16 #version 330
17 smooth in vec4 frag_color;
18 out vec4 out_color;
19 
20 void main() {
21 	out_color = frag_color;
22 }
23 `;
24 
25 string color_frag_shader_transparent = `
26 #version 330
27 smooth in vec4 frag_color;
28 out vec4 out_color;
29 uniform float transparency;
30 
31 void main() {
32 	out_color = vec4(frag_color.xyz, transparency);
33 }
34 `;
35 
36 string vert_shader_2d = `
37 #version 330
38 layout(location = 0) in vec2 position;
39 layout(location = 1) in vec4 color;
40 
41 smooth out vec4 frag_color;
42 uniform mat4 projection;
43 
44 void main() {
45 	gl_Position = projection * vec4(position.xy, 0, 1);
46 	frag_color = color;
47 }
48 `;
49 
50 string solid_vert_shader = `
51 #version 330
52 layout(location = 0) in vec4 position;
53 layout(location = 1) in vec4 color;
54 uniform mat4 projection;
55 uniform mat4 view;
56 uniform mat4 model;
57 smooth out vec4 frag_color;
58 void main() {
59 	gl_Position = projection * view * model * position;
60 	frag_color = color;
61 }
62 `;
63 
64 string tex_col_pos_vert_shader_2d = `
65 #version 330
66 uniform mat4 projection_uniform;
67 layout(location = 0) in vec4 position;
68 layout(location = 1) in vec2 uv;
69 layout(location = 2) in vec4 color;
70 out vec2 frag_uv;
71 smooth out vec4 frag_color;
72 
73 void main() {
74 	frag_uv = uv;
75 	frag_color = color;
76 	gl_Position = projection_uniform * position;
77 }
78 `;
79 
80 string tex_col_frag_shader = `
81 #version 330
82 uniform sampler2D tex_uniform;
83 in vec2 frag_uv;
84 smooth in vec4 frag_color;
85 out vec4 out_color;
86 
87 void main() {
88 	vec4 color = frag_color * texture(tex_uniform, frag_uv.st / textureSize(tex_uniform, 0));
89 	if (color.a == 0)
90 		discard;
91 	out_color = color;
92 }
93 `;
94 
95 immutable Matrix4f matrix4fIdentity = Matrix4f.identity;
96 
97 mixin template ModelSetter()
98 {
99 	void setModel(Matrix4f model) {
100 		checkgl!glUniformMatrix4fv(model_location, 1, GL_FALSE, model.arrayof.ptr);
101 	}
102 
103 	void setModel() {
104 		checkgl!glUniformMatrix4fv(model_location, 1, GL_FALSE, Matrix4f.identity.arrayof.ptr);
105 	}
106 }
107 
108 mixin template ViewSetter()
109 {
110 	void setView(Matrix4f view) {
111 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, view.arrayof.ptr);
112 	}
113 
114 	void setView() {
115 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, Matrix4f.identity.arrayof.ptr);
116 	}
117 }
118 
119 mixin template ProjectionSetter()
120 {
121 	void setProjection(Matrix4f projection) {
122 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, projection.arrayof.ptr);
123 	}
124 
125 	void setProjection() {
126 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, Matrix4f.identity.arrayof.ptr);
127 	}
128 }
129 
130 mixin template TransparencySetter() {
131 	void setTransparency(float transparency) {
132 		checkgl!glUniform1f(transparency_location, transparency);
133 	}
134 }
135 
136 mixin template TextureSetter() {
137 	void setTexture(int textureUnit) {
138 		checkgl!glUniform1i(uv_location, textureUnit);
139 	}
140 }
141 
142 mixin template MvpSetter()
143 {
144 	void setMVP(Matrix4f model, Matrix4f view, Matrix4f projection) {
145 		checkgl!glUniformMatrix4fv(model_location, 1, GL_FALSE, model.arrayof.ptr);
146 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, view.arrayof.ptr);
147 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, projection.arrayof.ptr);
148 	}
149 }
150 
151 mixin template VpSetter()
152 {
153 	void setVP(Matrix4f view, Matrix4f projection) {
154 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, view.arrayof.ptr);
155 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, projection.arrayof.ptr);
156 	}
157 }
158 
159 struct SolidShader3d
160 {
161 	ShaderProgram shader;
162 	alias shader this;
163 
164 	mixin MvpSetter;
165 	mixin VpSetter;
166 	mixin ModelSetter;
167 	mixin ViewSetter;
168 	mixin ProjectionSetter;
169 
170 	GLint model_location = -1;
171 	GLint view_location = -1;
172 	GLint projection_location = -1;
173 
174 	void compile(IRenderer renderer) {
175 		shader = renderer.createShaderProgram(solid_vert_shader, solid_frag_shader);
176 
177 		model_location = checkgl!glGetUniformLocation(handle, "model");
178 		view_location = checkgl!glGetUniformLocation(handle, "view");
179 		projection_location = checkgl!glGetUniformLocation(handle, "projection");
180 	}
181 }
182 
183 struct TransparentShader3d
184 {
185 	ShaderProgram shader;
186 	alias shader this;
187 
188 	mixin MvpSetter;
189 	mixin VpSetter;
190 	mixin ModelSetter;
191 	mixin ViewSetter;
192 	mixin ProjectionSetter;
193 	mixin TransparencySetter;
194 
195 	GLint model_location = -1;
196 	GLint view_location = -1;
197 	GLint projection_location = -1;
198 	GLint transparency_location = -1;
199 
200 	void compile(IRenderer renderer) {
201 		shader = renderer.createShaderProgram(solid_vert_shader, color_frag_shader_transparent);
202 
203 		model_location = checkgl!glGetUniformLocation(handle, "model");
204 		view_location = checkgl!glGetUniformLocation(handle, "view");
205 		projection_location = checkgl!glGetUniformLocation(handle, "projection");
206 		transparency_location = checkgl!glGetUniformLocation(handle, "transparency");
207 	}
208 }
209 
210 struct SolidShader2d
211 {
212 	ShaderProgram shader;
213 	alias shader this;
214 
215 	mixin ProjectionSetter;
216 
217 	GLint projection_location = -1;
218 
219 	void compile(IRenderer renderer) {
220 		shader = renderer.createShaderProgram(vert_shader_2d, solid_frag_shader);
221 
222 		projection_location = checkgl!glGetUniformLocation(handle, "projection");
223 	}
224 }
225 
226 struct ColUvShader2d
227 {
228 	ShaderProgram shader;
229 	alias shader this;
230 
231 	mixin ProjectionSetter;
232 	mixin TextureSetter;
233 
234 	GLint projection_location = -1;
235 	GLint uv_location = -1;
236 
237 	void compile(IRenderer renderer) {
238 		shader = renderer.createShaderProgram(tex_col_pos_vert_shader_2d, tex_col_frag_shader);
239 
240 		projection_location = checkgl!glGetUniformLocation(handle, "projection_uniform");
241 		uv_location = checkgl!glGetUniformLocation(handle, "tex_uniform");
242 	}
243 }