1 /* 2 Copyright (c) 2017-2018 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.graphics.postproc; 29 30 import std.stdio; 31 import std.conv; 32 33 import dlib.math.vector; 34 35 import derelict.opengl; 36 37 import dagon.core.ownership; 38 import dagon.graphics.rc; 39 import dagon.graphics.framebuffer; 40 41 class PostFilter: Owner 42 { 43 bool enabled = true; 44 Framebuffer inputBuffer; 45 Framebuffer outputBuffer; 46 47 GLenum shaderVert; 48 GLenum shaderFrag; 49 GLenum shaderProgram; 50 51 GLint modelViewMatrixLoc; 52 GLint prevModelViewProjMatrixLoc; 53 GLint projectionMatrixLoc; 54 GLint fbColorLoc; 55 GLint viewportSizeLoc; 56 GLint enabledLoc; 57 58 private string vsText = 59 q{ 60 #version 330 core 61 62 uniform mat4 modelViewMatrix; 63 uniform mat4 projectionMatrix; 64 65 uniform vec2 viewSize; 66 67 layout (location = 0) in vec2 va_Vertex; 68 layout (location = 1) in vec2 va_Texcoord; 69 70 out vec2 texCoord; 71 72 void main() 73 { 74 texCoord = va_Texcoord; 75 gl_Position = projectionMatrix * modelViewMatrix * vec4(va_Vertex * viewSize, 0.0, 1.0); 76 } 77 }; 78 79 private string fsText = 80 q{ 81 #version 330 core 82 83 uniform sampler2D fbColor; 84 uniform vec2 viewSize; 85 86 in vec2 texCoord; 87 out vec4 frag_color; 88 89 void main() 90 { 91 vec4 t = texture(fbColor, texCoord); 92 frag_color = t; 93 frag_color.a = 1.0; 94 } 95 }; 96 97 string vertexShader() {return vsText;} 98 string fragmentShader() {return fsText;} 99 100 this(Framebuffer inputBuffer, Framebuffer outputBuffer, Owner o) 101 { 102 super(o); 103 104 this.inputBuffer = inputBuffer; 105 this.outputBuffer = outputBuffer; 106 107 const(char*)pvs = vertexShader().ptr; 108 const(char*)pfs = fragmentShader().ptr; 109 110 char[1000] infobuffer = 0; 111 int infobufferlen = 0; 112 113 shaderVert = glCreateShader(GL_VERTEX_SHADER); 114 glShaderSource(shaderVert, 1, &pvs, null); 115 glCompileShader(shaderVert); 116 GLint success = 0; 117 glGetShaderiv(shaderVert, GL_COMPILE_STATUS, &success); 118 if (!success) 119 { 120 GLint logSize = 0; 121 glGetShaderiv(shaderVert, GL_INFO_LOG_LENGTH, &logSize); 122 glGetShaderInfoLog(shaderVert, 999, &logSize, infobuffer.ptr); 123 writeln("Error in vertex shader:"); 124 writeln(infobuffer[0..logSize]); 125 } 126 127 shaderFrag = glCreateShader(GL_FRAGMENT_SHADER); 128 glShaderSource(shaderFrag, 1, &pfs, null); 129 glCompileShader(shaderFrag); 130 success = 0; 131 glGetShaderiv(shaderFrag, GL_COMPILE_STATUS, &success); 132 if (!success) 133 { 134 GLint logSize = 0; 135 glGetShaderiv(shaderFrag, GL_INFO_LOG_LENGTH, &logSize); 136 glGetShaderInfoLog(shaderFrag, 999, &logSize, infobuffer.ptr); 137 writeln("Error in fragment shader:"); 138 writeln(infobuffer[0..logSize]); 139 } 140 141 shaderProgram = glCreateProgram(); 142 glAttachShader(shaderProgram, shaderVert); 143 glAttachShader(shaderProgram, shaderFrag); 144 glLinkProgram(shaderProgram); 145 146 modelViewMatrixLoc = glGetUniformLocation(shaderProgram, "modelViewMatrix"); 147 prevModelViewProjMatrixLoc = glGetUniformLocation(shaderProgram, "prevModelViewProjMatrix"); 148 projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix"); 149 150 viewportSizeLoc = glGetUniformLocation(shaderProgram, "viewSize"); 151 fbColorLoc = glGetUniformLocation(shaderProgram, "fbColor"); 152 enabledLoc = glGetUniformLocation(shaderProgram, "enabled"); 153 } 154 155 void bind(RenderingContext* rc) 156 { 157 glUseProgram(shaderProgram); 158 159 glUniformMatrix4fv(modelViewMatrixLoc, 1, 0, rc.viewMatrix.arrayof.ptr); 160 glUniformMatrix4fv(projectionMatrixLoc, 1, 0, rc.projectionMatrix.arrayof.ptr); 161 162 glUniformMatrix4fv(prevModelViewProjMatrixLoc, 1, 0, rc.prevModelViewProjMatrix.arrayof.ptr); 163 164 Vector2f viewportSize; 165 166 if (outputBuffer) 167 viewportSize = Vector2f(outputBuffer.width, outputBuffer.height); 168 else 169 viewportSize = Vector2f(rc.eventManager.windowWidth, rc.eventManager.windowHeight); 170 glUniform2fv(viewportSizeLoc, 1, viewportSize.arrayof.ptr); 171 172 glActiveTexture(GL_TEXTURE0); 173 glBindTexture(GL_TEXTURE_2D, inputBuffer.colorTexture); 174 175 glUniform1i(fbColorLoc, 0); 176 177 glUniform1i(enabledLoc, enabled); 178 } 179 180 void unbind(RenderingContext* rc) 181 { 182 glActiveTexture(GL_TEXTURE0); 183 glBindTexture(GL_TEXTURE_2D, 0); 184 185 glActiveTexture(GL_TEXTURE0); 186 187 glUseProgram(0); 188 } 189 190 void render(RenderingContext* rc) 191 { 192 bind(rc); 193 inputBuffer.render(); 194 unbind(rc); 195 } 196 }