1 /**
2 Copyright: Copyright (c) 2017 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 derelict.opengl3.gl3;
10 import anchovy.irenderer;
11 import anchovy.shaderprogram;
12 import anchovy.glerrors;
13 import voxelman.math;
14 
15 
16 string solid_frag_shader = `
17 #version 330
18 smooth in vec4 frag_color;
19 out vec4 out_color;
20 
21 void main() {
22 	out_color = frag_color;
23 }
24 `;
25 
26 string color_frag_shader_transparent = `
27 #version 330
28 smooth in vec4 frag_color;
29 out vec4 out_color;
30 uniform float transparency;
31 
32 void main() {
33 	out_color = vec4(frag_color.xyz, transparency);
34 }
35 `;
36 
37 string vert_shader_2d = `
38 #version 330
39 layout(location = 0) in vec2 position;
40 layout(location = 1) in vec4 color;
41 
42 smooth out vec4 frag_color;
43 uniform mat4 projection;
44 
45 void main() {
46 	gl_Position = projection * vec4(position.xy, 0, 1);
47 	frag_color = color;
48 }
49 `;
50 
51 string solid_vert_shader = `
52 #version 330
53 layout(location = 0) in vec4 position;
54 layout(location = 1) in vec4 color;
55 uniform mat4 projection;
56 uniform mat4 view;
57 uniform mat4 model;
58 smooth out vec4 frag_color;
59 void main() {
60 	gl_Position = projection * view * model * position;
61 	frag_color = color;
62 }
63 `;
64 
65 immutable Matrix4f matrix4fIdentity = Matrix4f.identity;
66 
67 mixin template ModelSetter()
68 {
69 	void setModel(Matrix4f model) {
70 		checkgl!glUniformMatrix4fv(model_location, 1, GL_FALSE, model.arrayof.ptr);
71 	}
72 
73 	void setModel() {
74 		checkgl!glUniformMatrix4fv(model_location, 1, GL_FALSE, Matrix4f.identity.arrayof.ptr);
75 	}
76 }
77 
78 mixin template ViewSetter()
79 {
80 	void setView(Matrix4f view) {
81 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, view.arrayof.ptr);
82 	}
83 
84 	void setView() {
85 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, Matrix4f.identity.arrayof.ptr);
86 	}
87 }
88 
89 mixin template ProjectionSetter()
90 {
91 	void setProjection(Matrix4f projection) {
92 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, projection.arrayof.ptr);
93 	}
94 
95 	void setProjection() {
96 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, Matrix4f.identity.arrayof.ptr);
97 	}
98 }
99 
100 mixin template TransparencySetter() {
101 	void setTransparency(float transparency) {
102 		checkgl!glUniform1f(transparency_location, transparency);
103 	}
104 }
105 
106 mixin template MvpSetter()
107 {
108 	void setMVP(Matrix4f model, Matrix4f view, Matrix4f projection) {
109 		checkgl!glUniformMatrix4fv(model_location, 1, GL_FALSE, model.arrayof.ptr);
110 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, view.arrayof.ptr);
111 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, projection.arrayof.ptr);
112 	}
113 }
114 
115 mixin template VpSetter()
116 {
117 	void setVP(Matrix4f view, Matrix4f projection) {
118 		checkgl!glUniformMatrix4fv(view_location, 1, GL_FALSE, view.arrayof.ptr);
119 		checkgl!glUniformMatrix4fv(projection_location, 1, GL_FALSE, projection.arrayof.ptr);
120 	}
121 }
122 
123 struct SolidShader3d
124 {
125 	ShaderProgram shader;
126 	alias shader this;
127 
128 	mixin MvpSetter;
129 	mixin VpSetter;
130 	mixin ModelSetter;
131 	mixin ViewSetter;
132 	mixin ProjectionSetter;
133 
134 	GLint model_location = -1;
135 	GLint view_location = -1;
136 	GLint projection_location = -1;
137 
138 	void compile(IRenderer renderer) {
139 		shader = renderer.createShaderProgram(solid_vert_shader, solid_frag_shader);
140 
141 		model_location = checkgl!glGetUniformLocation(shader.handle, "model");
142 		view_location = checkgl!glGetUniformLocation(shader.handle, "view");
143 		projection_location = checkgl!glGetUniformLocation(shader.handle, "projection");
144 	}
145 }
146 
147 struct TransparentShader3d
148 {
149 	ShaderProgram shader;
150 	alias shader this;
151 
152 	mixin MvpSetter;
153 	mixin VpSetter;
154 	mixin ModelSetter;
155 	mixin ViewSetter;
156 	mixin ProjectionSetter;
157 	mixin TransparencySetter;
158 
159 	GLint model_location = -1;
160 	GLint view_location = -1;
161 	GLint projection_location = -1;
162 	GLint transparency_location = -1;
163 
164 	void compile(IRenderer renderer) {
165 		shader = renderer.createShaderProgram(solid_vert_shader, color_frag_shader_transparent);
166 
167 		model_location = checkgl!glGetUniformLocation(shader.handle, "model");
168 		view_location = checkgl!glGetUniformLocation(shader.handle, "view");
169 		projection_location = checkgl!glGetUniformLocation(shader.handle, "projection");
170 		transparency_location = checkgl!glGetUniformLocation(shader.handle, "transparency");
171 	}
172 }
173 
174 struct SolidShader2d
175 {
176 	ShaderProgram shader;
177 	alias shader this;
178 
179 	mixin ProjectionSetter;
180 
181 	GLint projection_location = -1;
182 
183 	void compile(IRenderer renderer) {
184 		shader = renderer.createShaderProgram(vert_shader_2d, solid_frag_shader);
185 
186 		projection_location = checkgl!glGetUniformLocation(shader.handle, "projection");
187 	}
188 }