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 #version 330 core 60 61 uniform mat4 modelViewMatrix; 62 uniform mat4 projectionMatrix; 63 64 uniform vec2 viewSize; 65 66 layout (location = 0) in vec2 va_Vertex; 67 layout (location = 1) in vec2 va_Texcoord; 68 69 out vec2 texCoord; 70 71 void main() 72 { 73 texCoord = va_Texcoord; 74 gl_Position = projectionMatrix * modelViewMatrix * vec4(va_Vertex * viewSize, 0.0, 1.0); 75 } 76 "; 77 78 private string fsText = " 79 #version 330 core 80 81 uniform sampler2D fbColor; 82 uniform vec2 viewSize; 83 84 in vec2 texCoord; 85 out vec4 frag_color; 86 87 void main() 88 { 89 vec4 t = texture(fbColor, texCoord); 90 frag_color = t; 91 frag_color.a = 1.0; 92 } 93 "; 94 95 string vertexShader() {return vsText;} 96 string fragmentShader() {return fsText;} 97 98 this(Framebuffer inputBuffer, Framebuffer outputBuffer, Owner o) 99 { 100 super(o); 101 102 this.inputBuffer = inputBuffer; 103 this.outputBuffer = outputBuffer; 104 105 const(char*)pvs = vertexShader().ptr; 106 const(char*)pfs = fragmentShader().ptr; 107 108 char[1000] infobuffer = 0; 109 int infobufferlen = 0; 110 111 shaderVert = glCreateShader(GL_VERTEX_SHADER); 112 glShaderSource(shaderVert, 1, &pvs, null); 113 glCompileShader(shaderVert); 114 GLint success = 0; 115 glGetShaderiv(shaderVert, GL_COMPILE_STATUS, &success); 116 if (!success) 117 { 118 GLint logSize = 0; 119 glGetShaderiv(shaderVert, GL_INFO_LOG_LENGTH, &logSize); 120 glGetShaderInfoLog(shaderVert, 999, &logSize, infobuffer.ptr); 121 writeln("Error in vertex shader:"); 122 writeln(infobuffer[0..logSize]); 123 } 124 125 shaderFrag = glCreateShader(GL_FRAGMENT_SHADER); 126 glShaderSource(shaderFrag, 1, &pfs, null); 127 glCompileShader(shaderFrag); 128 success = 0; 129 glGetShaderiv(shaderFrag, GL_COMPILE_STATUS, &success); 130 if (!success) 131 { 132 GLint logSize = 0; 133 glGetShaderiv(shaderFrag, GL_INFO_LOG_LENGTH, &logSize); 134 glGetShaderInfoLog(shaderFrag, 999, &logSize, infobuffer.ptr); 135 writeln("Error in fragment shader:"); 136 writeln(infobuffer[0..logSize]); 137 } 138 139 shaderProgram = glCreateProgram(); 140 glAttachShader(shaderProgram, shaderVert); 141 glAttachShader(shaderProgram, shaderFrag); 142 glLinkProgram(shaderProgram); 143 144 modelViewMatrixLoc = glGetUniformLocation(shaderProgram, "modelViewMatrix"); 145 prevModelViewProjMatrixLoc = glGetUniformLocation(shaderProgram, "prevModelViewProjMatrix"); 146 projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix"); 147 148 viewportSizeLoc = glGetUniformLocation(shaderProgram, "viewSize"); 149 fbColorLoc = glGetUniformLocation(shaderProgram, "fbColor"); 150 enabledLoc = glGetUniformLocation(shaderProgram, "enabled"); 151 } 152 153 void bind(RenderingContext* rc) 154 { 155 glUseProgram(shaderProgram); 156 157 glUniformMatrix4fv(modelViewMatrixLoc, 1, 0, rc.viewMatrix.arrayof.ptr); 158 glUniformMatrix4fv(projectionMatrixLoc, 1, 0, rc.projectionMatrix.arrayof.ptr); 159 160 glUniformMatrix4fv(prevModelViewProjMatrixLoc, 1, 0, rc.prevModelViewProjMatrix.arrayof.ptr); 161 162 Vector2f viewportSize; 163 164 if (outputBuffer) 165 viewportSize = Vector2f(outputBuffer.width, outputBuffer.height); 166 else 167 viewportSize = Vector2f(rc.eventManager.windowWidth, rc.eventManager.windowHeight); 168 glUniform2fv(viewportSizeLoc, 1, viewportSize.arrayof.ptr); 169 170 glActiveTexture(GL_TEXTURE0); 171 glBindTexture(GL_TEXTURE_2D, inputBuffer.colorTexture); 172 173 glUniform1i(fbColorLoc, 0); 174 175 glUniform1i(enabledLoc, enabled); 176 } 177 178 void unbind(RenderingContext* rc) 179 { 180 glActiveTexture(GL_TEXTURE0); 181 glBindTexture(GL_TEXTURE_2D, 0); 182 183 glActiveTexture(GL_TEXTURE0); 184 185 glUseProgram(0); 186 } 187 188 void render(RenderingContext* rc) 189 { 190 bind(rc); 191 inputBuffer.render(); 192 unbind(rc); 193 } 194 }