1 /**
2 Copyright: Copyright (c) 2015-2016 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.plugin;
8 
9 import std.experimental.logger;
10 import derelict.opengl3.gl3;
11 import voxelman.container.buffer;
12 import voxelman.math;
13 import dlib.math.matrix;
14 
15 import pluginlib;
16 import anchovy.irenderer;
17 import anchovy.shaderprogram;
18 import voxelman.core.config;
19 import voxelman.core.events;
20 import voxelman.eventdispatcher.plugin;
21 import voxelman.gui.plugin;
22 import voxelman.config.configmanager;
23 import voxelman.utils.fpscamera;
24 public import voxelman.graphics;
25 
26 
27 shared static this()
28 {
29 	pluginRegistry.regClientPlugin(new GraphicsPlugin);
30 }
31 
32 string color_frag_shader = `
33 #version 330
34 smooth in vec4 theColor;
35 out vec4 outputColor;
36 const vec4 fogcolor = vec4(0.6, 0.8, 1.0, 1.0);
37 const float fogdensity = .00001;
38 vec4 gamma(vec4 color) {
39 	return vec4(pow(color.xyz, vec3(1.0/2.0)), color.a);
40 }
41 void main() {
42 	float z = gl_FragCoord.z / gl_FragCoord.w;
43 	float fogModifier = clamp(exp(-fogdensity * z * z), 0.0, 1);
44 	outputColor = (mix(fogcolor, theColor, fogModifier));
45 }
46 `;
47 
48 string color_frag_shader_transparent = `
49 #version 330
50 smooth in vec4 theColor;
51 out vec4 outputColor;
52 const vec4 fogcolor = vec4(0.6, 0.8, 1.0, 1.0);
53 const float fogdensity = .00001;
54 vec4 gamma(vec4 color) {
55 	return vec4(pow(color.xyz, vec3(1.0/2.0)), color.a);
56 }
57 void main() {
58 	float z = gl_FragCoord.z / gl_FragCoord.w;
59 	float fogModifier = clamp(exp(-fogdensity * z * z), 0.0, 1);
60 	outputColor = (vec4(mix(fogcolor, theColor, fogModifier).xyz, 0.5));
61 }
62 `;
63 
64 string solid_vert_shader = `
65 #version 330
66 layout(location = 0) in vec4 position;
67 layout(location = 1) in vec4 color;
68 uniform mat4 projection;
69 uniform mat4 view;
70 uniform mat4 model;
71 smooth out vec4 theColor;
72 void main() {
73 	gl_Position = projection * view * model * position;
74 	theColor = color;
75 }
76 `;
77 
78 string chunk_vert_shader = `
79 #version 330
80 layout(location = 0) in vec4 position;
81 layout(location = 1) in vec4 color;
82 uniform mat4 projection;
83 uniform mat4 view;
84 uniform mat4 model;
85 smooth out vec4 theColor;
86 void main() {
87 	gl_Position = projection * view * model * (position);
88 	//vec4 unpackedColor = vec4(1,1,1,1);
89 	//vec4 unpackedColor = vec4((color & 31)/31, ((color >> 5) & 31)/31, ((color >> 10) & 31)/31, 1);
90 	theColor = color;
91 }
92 `;
93 
94 final class GraphicsPlugin : IPlugin
95 {
96 private:
97 	uint vao;
98 	uint vbo;
99 	EventDispatcherPlugin evDispatcher;
100 
101 public:
102 	FpsCamera camera;
103 	Batch debugBatch;
104 
105 	ShaderProgram chunkShader;
106 	ShaderProgram solidShader;
107 	ShaderProgram transChunkShader;
108 
109 	IRenderer renderer;
110 	ConfigOption cameraSensivity;
111 	ConfigOption cameraFov;
112 
113 	GLuint projectionLoc = 2; //perspective
114 	GLuint viewLoc = 3; //camera trandformation
115 	GLuint modelLoc = 4; //model transformation
116 
117 
118 	mixin IdAndSemverFrom!(voxelman.graphics.plugininfo);
119 
120 	override void registerResources(IResourceManagerRegistry resmanRegistry)
121 	{
122 		auto config = resmanRegistry.getResourceManager!ConfigManager;
123 		cameraSensivity = config.registerOption!double("camera_sensivity", 0.4);
124 		cameraFov = config.registerOption!double("camera_fov", 60.0);
125 	}
126 
127 	override void preInit()
128 	{
129 		camera.move(START_POS);
130 		camera.sensivity = cameraSensivity.get!float;
131 		camera.fov = cameraFov.get!float;
132 	}
133 
134 	override void init(IPluginManager pluginman)
135 	{
136 		evDispatcher = pluginman.getPlugin!EventDispatcherPlugin;
137 		auto gui = pluginman.getPlugin!GuiPlugin;
138 
139 		evDispatcher.subscribeToEvent(&onWindowResizedEvent);
140 		evDispatcher.subscribeToEvent(&draw);
141 
142 		renderer = gui.renderer;
143 
144 		glGenVertexArrays(1, &vao);
145 		glGenBuffers( 1, &vbo);
146 
147 		// Setup shaders
148 		chunkShader = renderer.createShaderProgram(chunk_vert_shader, color_frag_shader);
149 		transChunkShader = renderer.createShaderProgram(chunk_vert_shader, color_frag_shader_transparent);
150 		solidShader = renderer.createShaderProgram(solid_vert_shader, color_frag_shader);
151 
152 		chunkShader.bind;
153 			modelLoc = glGetUniformLocation( solidShader.handle, "model" );//model transformation
154 			viewLoc = glGetUniformLocation( solidShader.handle, "view" );//camera trandformation
155 			projectionLoc = glGetUniformLocation( solidShader.handle, "projection" );//perspective
156 
157 			glUniformMatrix4fv(modelLoc, 1, GL_FALSE,
158 				cast(const float*)Matrix4f.identity.arrayof);
159 			glUniformMatrix4fv(viewLoc, 1, GL_FALSE,
160 				cast(const float*)camera.cameraMatrix);
161 			glUniformMatrix4fv(projectionLoc, 1, GL_FALSE,
162 				cast(const float*)camera.perspective.arrayof);
163 		chunkShader.unbind;
164 	}
165 
166 	override void postInit()
167 	{
168 		renderer.setClearColor(165,211,238);
169 		camera.aspect = cast(float)renderer.framebufferSize.x/renderer.framebufferSize.y;
170 	}
171 
172 	private void onWindowResizedEvent(ref WindowResizedEvent event)
173 	{
174 		camera.aspect = cast(float)event.newSize.x/event.newSize.y;
175 	}
176 
177 	void resetCamera()
178 	{
179 		camera.position = vec3(0,0,0);
180 		camera.target = vec3(0,0,1);
181 		camera.heading = vec2(0, 0);
182 		camera.update();
183 	}
184 
185 	private void draw(ref RenderEvent event)
186 	{
187 		glScissor(0, 0, renderer.framebufferSize.x, renderer.framebufferSize.y);
188 		glViewport(0, 0, renderer.framebufferSize.x, renderer.framebufferSize.y);
189 		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
190 		glEnable(GL_DEPTH_TEST);
191 
192 		draw(debugBatch);
193 		debugBatch.reset();
194 
195 		evDispatcher.postEvent(RenderSolid3dEvent(renderer));
196 
197 		glDisable(GL_DEPTH_TEST);
198 
199 		renderer.enableAlphaBlending();
200 
201 		evDispatcher.postEvent(RenderTransparent3dEvent(renderer));
202 
203 		renderer.enableAlphaBlending();
204 		evDispatcher.postEvent(Render2Event(renderer));
205 		evDispatcher.postEvent(Render3Event(renderer));
206 		renderer.disableAlphaBlending();
207 		renderer.flush();
208 	}
209 
210 	void draw(Batch batch)
211 	{
212 		solidShader.bind;
213 		drawBuffer(batch.triBuffer, GL_TRIANGLES);
214 		drawBuffer(batch.lineBuffer, GL_LINES);
215 		drawBuffer(batch.pointBuffer, GL_POINTS);
216 		solidShader.unbind;
217 	}
218 
219 private:
220 
221 	void drawBuffer(ref Buffer!ColoredVertex buffer, uint mode)
222 	{
223 		if (buffer.length == 0) return;
224 
225 		glUniformMatrix4fv(modelLoc, 1, GL_FALSE, cast(const float*)Matrix4f.identity.arrayof);
226 		glUniformMatrix4fv(viewLoc, 1, GL_FALSE, camera.cameraMatrix);
227 		glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, cast(const float*)camera.perspective.arrayof);
228 		glBindVertexArray(vao);
229 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
230 		glBufferData(GL_ARRAY_BUFFER, buffer.length*ColoredVertex.sizeof, buffer.buf.ptr, GL_DYNAMIC_DRAW);
231 		glEnableVertexAttribArray(0);
232 		glEnableVertexAttribArray(1);
233 		// positions
234 		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, ColoredVertex.sizeof, null);
235 		// color
236 		glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_TRUE, ColoredVertex.sizeof, cast(void*)(12));
237 		glBindBuffer(GL_ARRAY_BUFFER, 0);
238 
239 		glDrawArrays(mode, 0, cast(uint)(buffer.length));
240 
241 		glBindVertexArray(0);
242 	}
243 }