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.filters.lens; 29 30 import derelict.opengl; 31 import dagon.core.ownership; 32 import dagon.graphics.postproc; 33 import dagon.graphics.framebuffer; 34 import dagon.graphics.rc; 35 36 /* 37 * Implementation is based on a code by Jaume Sanchez: 38 * https://github.com/spite/Wagner 39 */ 40 41 class PostFilterLensDistortion: PostFilter 42 { 43 private string vs = q{ 44 #version 330 core 45 46 uniform mat4 modelViewMatrix; 47 uniform mat4 projectionMatrix; 48 49 uniform vec2 viewSize; 50 51 layout (location = 0) in vec2 va_Vertex; 52 layout (location = 1) in vec2 va_Texcoord; 53 54 out vec2 texCoord; 55 56 void main() 57 { 58 texCoord = va_Texcoord; 59 gl_Position = projectionMatrix * modelViewMatrix * vec4(va_Vertex * viewSize, 0.0, 1.0); 60 } 61 }; 62 63 private string fs = q{ 64 #version 330 core 65 66 uniform sampler2D fbColor; 67 uniform vec2 viewSize; 68 69 in vec2 texCoord; 70 out vec4 frag_color; 71 72 vec2 barrelDistortion(vec2 coord, float amt) 73 { 74 vec2 cc = coord - 0.5; 75 float dist = dot(cc, cc); 76 return coord + cc * dist * amt; 77 } 78 79 float sat(float t) 80 { 81 return clamp(t, 0.0, 1.0); 82 } 83 84 float linterp(float t) 85 { 86 return sat(1.0 - abs(2.0 * t - 1.0)); 87 } 88 89 float remap(float t, float a, float b) 90 { 91 return sat((t - a) / (b - a)); 92 } 93 94 vec4 spectrumOffset(float t) 95 { 96 vec4 ret; 97 float lo = step(t, 0.5); 98 float hi = 1.0 - lo; 99 float w = linterp(remap(t, 1.0/6.0, 5.0/6.0)); 100 ret = vec4(lo, 1.0, hi, 1.0) * vec4(1.0 - w, w, 1.0 - w, 1.0); 101 return pow(ret, vec4(1.0 / 2.2)); 102 } 103 104 uniform float scale; 105 uniform float dispersion; 106 107 const int num_iter = 12; 108 const float reci_num_iter_f = 1.0 / float(num_iter); 109 110 void main() 111 { 112 vec2 uv = texCoord * scale + (1.0 - scale) * 0.5; 113 114 vec4 sumcol = vec4(0.0); 115 vec4 sumw = vec4(0.0); 116 for (int i = 0; i < num_iter; ++i) 117 { 118 float t = float(i) * reci_num_iter_f; 119 vec4 w = spectrumOffset(t); 120 sumw += w; 121 sumcol += w * texture(fbColor, barrelDistortion(uv, 0.6 * dispersion * t)); 122 } 123 124 frag_color = sumcol / sumw; 125 frag_color.a = 1.0; 126 } 127 }; 128 129 override string vertexShader() 130 { 131 return vs; 132 } 133 134 override string fragmentShader() 135 { 136 return fs; 137 } 138 139 GLint scaleLoc; 140 GLint dispersionLoc; 141 142 float scale = 0.84; 143 float dispersion = 0.5; 144 145 this(Framebuffer inputBuffer, Framebuffer outputBuffer, Owner o) 146 { 147 super(inputBuffer, outputBuffer, o); 148 149 scaleLoc = glGetUniformLocation(shaderProgram, "scale"); 150 dispersionLoc = glGetUniformLocation(shaderProgram, "dispersion"); 151 } 152 153 override void bind(RenderingContext* rc) 154 { 155 super.bind(rc); 156 157 glUniform1f(scaleLoc, scale); 158 glUniform1f(dispersionLoc, dispersion); 159 } 160 }