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 }