1 /* 2 Copyright (c) 2019 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.game.postprocrenderer; 29 30 import dlib.core.memory; 31 import dlib.core.ownership; 32 33 import dagon.core.event; 34 import dagon.core.time; 35 import dagon.graphics.texture; 36 import dagon.resource.scene; 37 import dagon.render.pass; 38 import dagon.render.deferred; 39 import dagon.render.view; 40 import dagon.render.framebuffer; 41 import dagon.render.gbuffer; 42 import dagon.postproc.filterpass; 43 import dagon.postproc.blurpass; 44 import dagon.postproc.presentpass; 45 import dagon.postproc.shaders.brightpass; 46 import dagon.postproc.shaders.glow; 47 import dagon.postproc.shaders.motionblur; 48 import dagon.postproc.shaders.tonemap; 49 import dagon.postproc.shaders.fxaa; 50 import dagon.postproc.shaders.lut; 51 import dagon.postproc.shaders.lensdistortion; 52 import dagon.game.renderer; 53 54 import dagon.core.bindings; 55 56 class DoubleBuffer: Framebuffer 57 { 58 Framebuffer writeBuffer; 59 Framebuffer readBuffer; 60 61 this(Framebuffer writeBuffer, Framebuffer readBuffer, Owner owner) 62 { 63 super(owner); 64 //super(writeBuffer.width, writeBuffer.height, true, owner); 65 this.writeBuffer = writeBuffer; 66 this.readBuffer = readBuffer; 67 } 68 69 void swap() 70 { 71 auto w = writeBuffer; 72 writeBuffer = readBuffer; 73 readBuffer = w; 74 } 75 76 override GLuint colorTexture() 77 { 78 return readBuffer.colorTexture(); 79 } 80 81 override GLuint depthTexture() 82 { 83 return readBuffer.depthTexture(); 84 } 85 86 override void bind() 87 { 88 writeBuffer.bind(); 89 } 90 91 override void unbind() 92 { 93 writeBuffer.unbind(); 94 } 95 96 override void resize(uint width, uint height) 97 { 98 99 } 100 101 override void blitColorBuffer() 102 { 103 104 } 105 106 override void blitDepthBuffer() 107 { 108 109 } 110 } 111 112 class PostProcRenderer: Renderer 113 { 114 public: 115 116 Framebuffer inputBuffer; 117 Framebuffer outputBuffer; 118 119 protected: 120 121 DoubleBuffer ldrDoubleBuffer; 122 123 Framebuffer ldrBuffer1; 124 Framebuffer ldrBuffer2; 125 126 Framebuffer hdrBuffer1; 127 Framebuffer hdrBuffer2; 128 Framebuffer hdrBuffer3; 129 Framebuffer hdrBuffer4; 130 131 RenderView viewHalf; 132 BlurPass passBlur; 133 134 BrightPassShader brightPassShader; 135 GlowShader glowShader; 136 MotionBlurShader motionBlurShader; 137 TonemapShader tonemapShader; 138 FXAAShader fxaaShader; 139 LensDistortionShader lensDistortionShader; 140 LUTShader lutShader; 141 142 FilterPass passMotionBlur; 143 FilterPass passBrightPass; 144 FilterPass passGlow; 145 FilterPass passTonemap; 146 FilterPass passFXAA; 147 FilterPass passLensDistortion; 148 FilterPass passLUT; 149 PresentPass passPresent; 150 151 bool _motionBlurEnabled = false; 152 bool _glowEnabled = false; 153 154 public: 155 156 float glowViewScale = 0.33f; 157 158 float glowThreshold = 0.8f; 159 float glowIntensity = 0.2f; 160 int glowRadius = 5; 161 Tonemapper tonemapper = Tonemapper.ACES; 162 float exposure = 1.0f; 163 164 uint motionBlurSamples = 16; 165 uint motionBlurFramerate = 24; 166 167 Texture colorLookupTable; 168 169 this(EventManager eventManager, Framebuffer inputBuffer, GBuffer gbuffer, Owner owner) 170 { 171 super(eventManager, owner); 172 173 this.inputBuffer = inputBuffer; 174 175 viewHalf = New!RenderView(0, 0, cast(uint)(view.width * glowViewScale), cast(uint)(view.height * glowViewScale), this); 176 177 ldrBuffer1 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA8, true, this); 178 ldrBuffer2 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA8, true, this); 179 ldrDoubleBuffer = New!DoubleBuffer(ldrBuffer1, ldrBuffer2, this); 180 181 hdrBuffer1 = New!Framebuffer(viewHalf.width, viewHalf.height, FrameBufferFormat.RGBA16F, true, this); 182 hdrBuffer2 = New!Framebuffer(viewHalf.width, viewHalf.height, FrameBufferFormat.RGBA16F, true, this); 183 184 hdrBuffer3 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA16F, true, this); 185 hdrBuffer4 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA16F, true, this); 186 187 motionBlurShader = New!MotionBlurShader(this); 188 motionBlurShader.gbuffer = gbuffer; 189 passMotionBlur = New!FilterPass(pipeline, motionBlurShader); 190 passMotionBlur.view = view; 191 passMotionBlur.inputBuffer = inputBuffer; 192 passMotionBlur.outputBuffer = hdrBuffer4; 193 194 brightPassShader = New!BrightPassShader(this); 195 brightPassShader.luminanceThreshold = glowThreshold; 196 passBrightPass = New!FilterPass(pipeline, brightPassShader); 197 passBrightPass.view = viewHalf; 198 passBrightPass.inputBuffer = passMotionBlur.outputBuffer; 199 passBrightPass.outputBuffer = hdrBuffer1; 200 201 passBlur = New!BlurPass(pipeline); 202 passBlur.view = viewHalf; 203 passBlur.inputBuffer = passBrightPass.outputBuffer; 204 passBlur.outputBuffer = hdrBuffer1; 205 passBlur.outputBuffer2 = hdrBuffer2; 206 passBlur.radius = glowRadius; 207 208 glowShader = New!GlowShader(this); 209 glowShader.blurredBuffer = passBlur.outputBuffer; 210 glowShader.intensity = glowIntensity; 211 passGlow = New!FilterPass(pipeline, glowShader); 212 passGlow.view = view; 213 passGlow.inputBuffer = passMotionBlur.outputBuffer; 214 passGlow.outputBuffer = hdrBuffer3; 215 216 tonemapShader = New!TonemapShader(this); 217 passTonemap = New!FilterPass(pipeline, tonemapShader); 218 passTonemap.view = view; 219 passTonemap.inputBuffer = passGlow.outputBuffer; 220 passTonemap.outputBuffer = ldrDoubleBuffer; 221 222 fxaaShader = New!FXAAShader(this); 223 passFXAA = New!FilterPass(pipeline, fxaaShader); 224 passFXAA.view = view; 225 passFXAA.inputBuffer = ldrDoubleBuffer; 226 passFXAA.outputBuffer = ldrDoubleBuffer; 227 228 lensDistortionShader = New!LensDistortionShader(this); 229 passLensDistortion = New!FilterPass(pipeline, lensDistortionShader); 230 passLensDistortion.view = view; 231 passLensDistortion.inputBuffer = ldrDoubleBuffer; 232 passLensDistortion.outputBuffer = ldrDoubleBuffer; 233 234 lutShader = New!LUTShader(this); 235 passLUT = New!FilterPass(pipeline, lutShader); 236 passLUT.view = view; 237 passLUT.inputBuffer = ldrDoubleBuffer; 238 passLUT.outputBuffer = ldrDoubleBuffer; 239 240 outputBuffer = ldrDoubleBuffer; 241 } 242 243 void motionBlurEnabled(bool mode) @property 244 { 245 _motionBlurEnabled = mode; 246 passMotionBlur.active = mode; 247 } 248 bool motionBlurEnabled() @property 249 { 250 return _motionBlurEnabled; 251 } 252 253 void glowEnabled(bool mode) @property 254 { 255 _glowEnabled = mode; 256 passBrightPass.active = mode; 257 passBlur.active = mode; 258 passGlow.active = mode; 259 } 260 bool glowEnabled() @property 261 { 262 return _glowEnabled; 263 } 264 265 void fxaaEnabled(bool mode) @property 266 { 267 passFXAA.active = mode; 268 } 269 bool fxaaEnabled() @property 270 { 271 return passFXAA.active; 272 } 273 274 void lensDistortionEnabled(bool mode) @property 275 { 276 passLensDistortion.active = mode; 277 } 278 bool lensDistortionEnabled() @property 279 { 280 return passLensDistortion.active; 281 } 282 283 void lutEnabled(bool mode) @property 284 { 285 passLUT.active = mode; 286 } 287 bool lutEnabled() @property 288 { 289 return passLUT.active; 290 } 291 292 override void update(Time t) 293 { 294 super.update(t); 295 296 brightPassShader.luminanceThreshold = glowThreshold; 297 glowShader.intensity = glowIntensity; 298 passBlur.radius = glowRadius; 299 tonemapShader.tonemapper = tonemapper; 300 tonemapShader.exposure = exposure; 301 motionBlurShader.samples = motionBlurSamples; 302 motionBlurShader.currentFramerate = 1.0 / t.delta; 303 motionBlurShader.shutterFramerate = motionBlurFramerate; 304 lutShader.colorLookupTable = colorLookupTable; 305 if (lutShader.colorLookupTable) 306 { 307 lutShader.colorLookupTable.useMipmapFiltering = false; 308 } 309 } 310 311 override void render() 312 { 313 if (outputBuffer) 314 outputBuffer.bind(); 315 316 if (!_motionBlurEnabled) 317 { 318 passBrightPass.inputBuffer = inputBuffer; 319 passGlow.inputBuffer = inputBuffer; 320 } 321 else 322 { 323 passBrightPass.inputBuffer = passMotionBlur.outputBuffer; 324 passGlow.inputBuffer = passMotionBlur.outputBuffer; 325 } 326 327 if (!_glowEnabled) 328 { 329 if (_motionBlurEnabled) 330 passTonemap.inputBuffer = passMotionBlur.outputBuffer; 331 else 332 passTonemap.inputBuffer = inputBuffer; 333 } 334 else 335 { 336 passTonemap.inputBuffer = passGlow.outputBuffer; 337 } 338 339 foreach(pass; pipeline.passes.data) 340 { 341 if (pass.active) 342 { 343 pass.render(); 344 ldrDoubleBuffer.swap(); 345 } 346 } 347 348 if (outputBuffer) 349 outputBuffer.unbind(); 350 } 351 352 override void setViewport(uint x, uint y, uint w, uint h) 353 { 354 super.setViewport(x, y, w, h); 355 356 viewHalf.resize(cast(uint)(view.width * glowViewScale), cast(uint)(view.height * glowViewScale)); 357 358 ldrBuffer1.resize(view.width, view.height); 359 ldrBuffer2.resize(view.width, view.height); 360 361 hdrBuffer1.resize(viewHalf.width, viewHalf.height); 362 hdrBuffer2.resize(viewHalf.width, viewHalf.height); 363 hdrBuffer3.resize(view.width, view.height); 364 hdrBuffer4.resize(view.width, view.height); 365 } 366 }