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 dagon.core.libs; 36 import dagon.core.ownership; 37 import dagon.graphics.rc; 38 import dagon.graphics.framebuffer; 39 40 class PostFilter: Owner 41 { 42 bool enabled = true; 43 Framebuffer inputBuffer; 44 Framebuffer outputBuffer; 45 46 GLenum shaderVert; 47 GLenum shaderFrag; 48 GLenum shaderProgram; 49 50 GLint modelViewMatrixLoc; 51 GLint prevModelViewProjMatrixLoc; 52 GLint projectionMatrixLoc; 53 GLint fbColorLoc; 54 GLint viewportSizeLoc; 55 GLint enabledLoc; 56 57 private string vsText = 58 q{ 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 q{ 80 #version 330 core 81 82 uniform sampler2D fbColor; 83 uniform vec2 viewSize; 84 85 in vec2 texCoord; 86 out vec4 frag_color; 87 88 void main() 89 { 90 vec4 t = texture(fbColor, texCoord); 91 frag_color = t; 92 frag_color.a = 1.0; 93 } 94 }; 95 96 string vertexShader() {return vsText;} 97 string fragmentShader() {return fsText;} 98 99 this(Framebuffer inputBuffer, Framebuffer outputBuffer, Owner o) 100 { 101 super(o); 102 103 this.inputBuffer = inputBuffer; 104 this.outputBuffer = outputBuffer; 105 106 const(char*)pvs = vertexShader().ptr; 107 const(char*)pfs = fragmentShader().ptr; 108 109 char[1000] infobuffer = 0; 110 int infobufferlen = 0; 111 112 shaderVert = glCreateShader(GL_VERTEX_SHADER); 113 glShaderSource(shaderVert, 1, &pvs, null); 114 glCompileShader(shaderVert); 115 GLint success = 0; 116 glGetShaderiv(shaderVert, GL_COMPILE_STATUS, &success); 117 if (!success) 118 { 119 GLint logSize = 0; 120 glGetShaderiv(shaderVert, GL_INFO_LOG_LENGTH, &logSize); 121 glGetShaderInfoLog(shaderVert, 999, &logSize, infobuffer.ptr); 122 writeln("Error in vertex shader:"); 123 writeln(infobuffer[0..logSize]); 124 } 125 126 shaderFrag = glCreateShader(GL_FRAGMENT_SHADER); 127 glShaderSource(shaderFrag, 1, &pfs, null); 128 glCompileShader(shaderFrag); 129 success = 0; 130 glGetShaderiv(shaderFrag, GL_COMPILE_STATUS, &success); 131 if (!success) 132 { 133 GLint logSize = 0; 134 glGetShaderiv(shaderFrag, GL_INFO_LOG_LENGTH, &logSize); 135 glGetShaderInfoLog(shaderFrag, 999, &logSize, infobuffer.ptr); 136 writeln("Error in fragment shader:"); 137 writeln(infobuffer[0..logSize]); 138 } 139 140 shaderProgram = glCreateProgram(); 141 glAttachShader(shaderProgram, shaderVert); 142 glAttachShader(shaderProgram, shaderFrag); 143 glLinkProgram(shaderProgram); 144 145 modelViewMatrixLoc = glGetUniformLocation(shaderProgram, "modelViewMatrix"); 146 prevModelViewProjMatrixLoc = glGetUniformLocation(shaderProgram, "prevModelViewProjMatrix"); 147 projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix"); 148 149 viewportSizeLoc = glGetUniformLocation(shaderProgram, "viewSize"); 150 fbColorLoc = glGetUniformLocation(shaderProgram, "fbColor"); 151 enabledLoc = glGetUniformLocation(shaderProgram, "enabled"); 152 } 153 154 void bind(RenderingContext* rc) 155 { 156 glUseProgram(shaderProgram); 157 158 glUniformMatrix4fv(modelViewMatrixLoc, 1, 0, rc.viewMatrix.arrayof.ptr); 159 glUniformMatrix4fv(projectionMatrixLoc, 1, 0, rc.projectionMatrix.arrayof.ptr); 160 161 glUniformMatrix4fv(prevModelViewProjMatrixLoc, 1, 0, rc.prevModelViewProjMatrix.arrayof.ptr); 162 163 Vector2f viewportSize; 164 165 auto colorTexture = inputBuffer.currentColorTexture; 166 167 if (outputBuffer) 168 viewportSize = Vector2f(outputBuffer.width, outputBuffer.height); 169 else 170 viewportSize = Vector2f(rc.eventManager.windowWidth, rc.eventManager.windowHeight); 171 glUniform2fv(viewportSizeLoc, 1, viewportSize.arrayof.ptr); 172 173 glActiveTexture(GL_TEXTURE0); 174 glBindTexture(GL_TEXTURE_2D, colorTexture); 175 176 glUniform1i(fbColorLoc, 0); 177 178 glUniform1i(enabledLoc, enabled); 179 } 180 181 void unbind(RenderingContext* rc) 182 { 183 glActiveTexture(GL_TEXTURE0); 184 glBindTexture(GL_TEXTURE_2D, 0); 185 186 glActiveTexture(GL_TEXTURE0); 187 188 glUseProgram(0); 189 } 190 191 void render(RenderingContext* rc) 192 { 193 bind(rc); 194 inputBuffer.render(); 195 unbind(rc); 196 } 197 }