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 }