1 /** 2 Copyright: Copyright (c) 2015-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.plugin; 8 9 import voxelman.log; 10 import derelict.opengl3.gl3; 11 import voxelman.container.buffer; 12 import voxelman.math; 13 14 import pluginlib; 15 import anchovy.iwindow; 16 import anchovy.irenderer; 17 import anchovy.shaderprogram; 18 import anchovy.glerrors; 19 import voxelman.core.config; 20 import voxelman.core.events; 21 import voxelman.eventdispatcher.plugin; 22 import voxelman.gui.plugin; 23 import voxelman.config.configmanager; 24 import voxelman.utils.fpscamera; 25 public import voxelman.graphics; 26 27 import voxelman.graphics.shaders; 28 29 final class GraphicsPlugin : IPlugin 30 { 31 private: 32 uint vao; 33 uint vbo; 34 EventDispatcherPlugin evDispatcher; 35 Matrix4f ortho_projection; 36 37 public: 38 FpsCamera camera; 39 Batch debugBatch; 40 Buffer!ColoredVertex transparentBuffer; 41 Batch2d overlayBatch; 42 43 SolidShader3d solidShader3d; 44 TransparentShader3d transparentShader3d; 45 SolidShader2d solidShader2d; 46 47 IRenderer renderer; 48 IWindow window; 49 50 ConfigOption cameraSensivity; 51 ConfigOption cameraFov; 52 53 mixin IdAndSemverFrom!"voxelman.graphics.plugininfo"; 54 55 override void registerResources(IResourceManagerRegistry resmanRegistry) 56 { 57 auto config = resmanRegistry.getResourceManager!ConfigManager; 58 cameraSensivity = config.registerOption!double("camera_sensivity", 0.4); 59 cameraFov = config.registerOption!double("camera_fov", 60.0); 60 } 61 62 override void preInit() 63 { 64 camera.move(vec3(0, 0, 0)); 65 camera.sensivity = cameraSensivity.get!float; 66 camera.fov = cameraFov.get!float; 67 } 68 69 override void init(IPluginManager pluginman) 70 { 71 evDispatcher = pluginman.getPlugin!EventDispatcherPlugin; 72 auto gui = pluginman.getPlugin!GuiPlugin; 73 74 evDispatcher.subscribeToEvent(&onWindowResizedEvent); 75 evDispatcher.subscribeToEvent(&draw); 76 77 renderer = gui.renderer; 78 window = gui.window; 79 80 glGenVertexArrays(1, &vao); 81 glGenBuffers( 1, &vbo); 82 83 // Setup shaders 84 solidShader3d.compile(renderer); 85 transparentShader3d.compile(renderer); 86 solidShader2d.compile(renderer); 87 88 ortho_projection.arrayof = 89 [ 90 2f/1, 0f, 0f, 0f, 91 0f, -2f/1, 0f, 0f, 92 0f, 0f, -1f, 0f, 93 -1f, 1f, 0f, 1f, 94 ]; 95 } 96 97 override void postInit() 98 { 99 renderer.setClearColor(165,211,238); 100 camera.aspect = cast(float)renderer.framebufferSize.x/renderer.framebufferSize.y; 101 updateOrtoMatrix(); 102 } 103 104 private void onWindowResizedEvent(ref WindowResizedEvent event) 105 { 106 camera.aspect = cast(float)event.newSize.x/event.newSize.y; 107 updateOrtoMatrix(); 108 } 109 110 void resetCamera() 111 { 112 camera.position = vec3(0,0,0); 113 camera.target = vec3(0,0,1); 114 camera.heading = vec2(0, 0); 115 camera.update(); 116 } 117 118 private void draw(ref RenderEvent event) 119 { 120 checkgl!glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 121 renderer.depthTest(true); 122 123 draw(debugBatch); 124 debugBatch.reset(); 125 126 evDispatcher.postEvent(RenderSolid3dEvent(renderer)); 127 128 renderer.depthTest(false); 129 renderer.alphaBlending(true); 130 131 evDispatcher.postEvent(RenderTransparent3dEvent(renderer)); 132 133 transparentShader3d.bind; 134 transparentShader3d.setMVP(Matrix4f.identity, camera.cameraMatrix, camera.perspective); 135 transparentShader3d.setTransparency(0.3f); 136 137 drawBuffer(transparentBuffer.data, GL_TRIANGLES); 138 transparentShader3d.unbind; 139 transparentBuffer.clear(); 140 141 evDispatcher.postEvent(Render2Event(renderer)); 142 143 draw(overlayBatch); 144 overlayBatch.reset(); 145 146 evDispatcher.postEvent(Render3Event(renderer)); 147 148 renderer.alphaBlending(false); 149 renderer.flush(); 150 } 151 152 void draw(Batch batch) 153 { 154 solidShader3d.bind; 155 solidShader3d.setMVP(Matrix4f.identity, camera.cameraMatrix, camera.perspective); 156 157 drawBuffer(batch.triBuffer.data, GL_TRIANGLES); 158 drawBuffer(batch.lineBuffer.data, GL_LINES); 159 drawBuffer(batch.pointBuffer.data, GL_POINTS); 160 161 solidShader3d.unbind; 162 } 163 164 void draw(Batch2d batch) 165 { 166 solidShader2d.bind; 167 solidShader2d.setProjection(ortho_projection); 168 169 drawBuffer(batch.triBuffer.data, GL_TRIANGLES); 170 drawBuffer(batch.lineBuffer.data, GL_LINES); 171 drawBuffer(batch.pointBuffer.data, GL_POINTS); 172 173 solidShader2d.unbind; 174 } 175 176 void drawBuffer3d(VertexType)(VertexType[] buffer, uint mode) 177 { 178 if (buffer.length == 0) return; 179 solidShader3d.bind; 180 solidShader3d.setMVP(Matrix4f.identity, camera.cameraMatrix, camera.perspective); 181 182 drawBuffer(buffer, mode); 183 184 solidShader3d.unbind; 185 } 186 187 private: 188 189 void updateOrtoMatrix() 190 { 191 renderer.setViewport(ivec2(0, 0), renderer.framebufferSize); 192 ortho_projection.a11 = 2f/renderer.framebufferSize.x; 193 ortho_projection.a22 = -2f/renderer.framebufferSize.y; 194 } 195 196 void drawBuffer(VertexType)(VertexType[] buffer, uint mode) 197 { 198 if (buffer.length == 0) return; 199 checkgl!glBindVertexArray(vao); 200 checkgl!glBindBuffer(GL_ARRAY_BUFFER, vbo); 201 checkgl!glBufferData(GL_ARRAY_BUFFER, buffer.length*VertexType.sizeof, buffer.ptr, GL_DYNAMIC_DRAW); 202 VertexType.setAttributes(); 203 checkgl!glBindBuffer(GL_ARRAY_BUFFER, 0); 204 checkgl!glDrawArrays(mode, 0, cast(uint)(buffer.length)); 205 checkgl!glBindVertexArray(0); 206 } 207 }