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 dlib.math.vector;
12 import dlib.math.matrix;
13 
14 import pluginlib;
15 import anchovy.irenderer;
16 import anchovy.shaderprogram;
17 import voxelman.core.config;
18 import voxelman.core.events;
19 import voxelman.eventdispatcher.plugin;
20 import voxelman.gui.plugin;
21 import voxelman.config.configmanager;
22 import voxelman.utils.fpscamera;
23 public import voxelman.utils.renderutils;
24 
25 
26 shared static this()
27 {
28 	pluginRegistry.regClientPlugin(new GraphicsPlugin);
29 }
30 
31 string color_frag_shader = `
32 #version 330
33 smooth in vec4 theColor;
34 out vec4 outputColor;
35 void main() { outputColor = theColor; }
36 `;
37 
38 string perspective_vert_shader = `
39 #version 330
40 layout(location = 0) in vec4 position;
41 layout(location = 1) in vec4 color;
42 smooth out vec4 theColor;
43 uniform mat4 projection;
44 uniform mat4 view;
45 uniform mat4 model;
46 void main() {
47 	gl_Position = projection * view * model * position;
48 	theColor = color;
49 }
50 `;
51 
52 final class GraphicsPlugin : IPlugin
53 {
54 private:
55 	uint vao;
56 	uint vbo;
57 	EventDispatcherPlugin evDispatcher;
58 
59 public:
60 	FpsCamera camera;
61 	Batch debugBatch;
62 
63 	ShaderProgram chunkShader;
64 	GLuint modelLoc, viewLoc, projectionLoc;
65 
66 	IRenderer renderer;
67 	ConfigOption cameraSensivity;
68 	ConfigOption cameraFov;
69 
70 
71 	mixin IdAndSemverFrom!(voxelman.graphics.plugininfo);
72 
73 	override void registerResources(IResourceManagerRegistry resmanRegistry)
74 	{
75 		auto config = resmanRegistry.getResourceManager!ConfigManager;
76 		cameraSensivity = config.registerOption!float("camera_sensivity", 0.4);
77 		cameraFov = config.registerOption!float("camera_fov", 60.0);
78 	}
79 
80 	override void preInit()
81 	{
82 		camera.move(START_POS);
83 		camera.sensivity = cameraSensivity.get!float;
84 		camera.fov = cameraFov.get!float;
85 	}
86 
87 	override void init(IPluginManager pluginman)
88 	{
89 		evDispatcher = pluginman.getPlugin!EventDispatcherPlugin;
90 		auto gui = pluginman.getPlugin!GuiPlugin;
91 
92 		evDispatcher.subscribeToEvent(&onWindowResizedEvent);
93 		evDispatcher.subscribeToEvent(&draw);
94 
95 		renderer = gui.renderer;
96 
97 		glGenVertexArrays(1, &vao);
98 		glGenBuffers( 1, &vbo);
99 
100 		// Setup shaders
101 		chunkShader = renderer.createShaderProgram(perspective_vert_shader, color_frag_shader);
102 
103 		chunkShader.bind;
104 			modelLoc = glGetUniformLocation( chunkShader.handle, "model" );//model transformation
105 			viewLoc = glGetUniformLocation( chunkShader.handle, "view" );//camera trandformation
106 			projectionLoc = glGetUniformLocation( chunkShader.handle, "projection" );//perspective
107 
108 			glUniformMatrix4fv(modelLoc, 1, GL_FALSE,
109 				cast(const float*)Matrix4f.identity.arrayof);
110 			glUniformMatrix4fv(viewLoc, 1, GL_FALSE,
111 				cast(const float*)camera.cameraMatrix);
112 			glUniformMatrix4fv(projectionLoc, 1, GL_FALSE,
113 				cast(const float*)camera.perspective.arrayof);
114 		chunkShader.unbind;
115 	}
116 
117 	override void postInit()
118 	{
119 		renderer.setClearColor(115,200,169);
120 		camera.aspect = cast(float)renderer.framebufferSize.x/renderer.framebufferSize.y;
121 	}
122 
123 	private void onWindowResizedEvent(ref WindowResizedEvent event)
124 	{
125 		camera.aspect = cast(float)event.newSize.x/event.newSize.y;
126 	}
127 
128 	void resetCamera()
129 	{
130 		camera.position = vec3(0,0,0);
131 		camera.target = vec3(0,0,1);
132 		camera.heading = vec2(0, 0);
133 		camera.update();
134 	}
135 
136 	private void draw(ref RenderEvent event)
137 	{
138 		glScissor(0, 0, renderer.framebufferSize.x, renderer.framebufferSize.y);
139 		glViewport(0, 0, renderer.framebufferSize.x, renderer.framebufferSize.y);
140 		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
141 		glEnable(GL_DEPTH_TEST);
142 
143 		evDispatcher.postEvent(Render1Event(renderer));
144 
145 		chunkShader.bind;
146 		draw(debugBatch);
147 		debugBatch.reset();
148 		chunkShader.unbind;
149 
150 		glDisable(GL_DEPTH_TEST);
151 
152 		renderer.enableAlphaBlending();
153 		evDispatcher.postEvent(Render2Event(renderer));
154 		evDispatcher.postEvent(Render3Event(renderer));
155 		renderer.disableAlphaBlending();
156 		{
157 			Zone subZone = Zone(event.profiler, "renderer.flush()");
158 			renderer.flush();
159 		}
160 	}
161 
162 	void draw(Batch batch)
163 	{
164 		drawBuffer(batch.triBuffer, GL_TRIANGLES);
165 		drawBuffer(batch.lineBuffer, GL_LINES);
166 		drawBuffer(batch.pointBuffer, GL_POINTS);
167 	}
168 
169 private:
170 
171 	void drawBuffer(ref ColoredVertex[] buffer, uint mode)
172 	{
173 		if (buffer.length == 0) return;
174 
175 		glBindVertexArray(vao);
176 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
177 		glBufferData(GL_ARRAY_BUFFER, buffer.length*ColoredVertex.sizeof, buffer.ptr, GL_DYNAMIC_DRAW);
178 		glEnableVertexAttribArray(0);
179 		glEnableVertexAttribArray(1);
180 		// positions
181 		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, ColoredVertex.sizeof, null);
182 		// color
183 		glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_TRUE, ColoredVertex.sizeof, cast(void*)(12));
184 		glBindBuffer(GL_ARRAY_BUFFER, 0);
185 
186 		glDrawArrays(mode, 0, cast(uint)(buffer.length));
187 
188 		glBindVertexArray(0);
189 	}
190 }