1 /* 2 Copyright (c) 2019-2020 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.dof; 46 import dagon.postproc.shaders.brightpass; 47 import dagon.postproc.shaders.glow; 48 import dagon.postproc.shaders.motionblur; 49 import dagon.postproc.shaders.tonemap; 50 import dagon.postproc.shaders.fxaa; 51 import dagon.postproc.shaders.lut; 52 import dagon.postproc.shaders.lensdistortion; 53 import dagon.game.renderer; 54 55 import dagon.core.bindings; 56 57 class DoubleBuffer: Framebuffer 58 { 59 Framebuffer writeBuffer; 60 Framebuffer readBuffer; 61 62 this(Framebuffer writeBuffer, Framebuffer readBuffer, Owner owner) 63 { 64 super(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 DepthOfFieldShader dofShader; 135 BrightPassShader brightPassShader; 136 GlowShader glowShader; 137 MotionBlurShader motionBlurShader; 138 TonemapShader tonemapShader; 139 FXAAShader fxaaShader; 140 LensDistortionShader lensDistortionShader; 141 LUTShader lutShader; 142 143 FilterPass passDoF; 144 FilterPass passMotionBlur; 145 FilterPass passBrightPass; 146 FilterPass passGlow; 147 FilterPass passTonemap; 148 FilterPass passFXAA; 149 FilterPass passLensDistortion; 150 FilterPass passLUT; 151 PresentPass passPresent; 152 153 bool _dofEnabled = false; 154 bool _motionBlurEnabled = false; 155 bool _glowEnabled = false; 156 157 public: 158 159 float glowViewScale = 0.33f; 160 161 float glowThreshold = 0.8f; 162 float glowIntensity = 0.2f; 163 int glowRadius = 5; 164 Tonemapper tonemapper = Tonemapper.ACES; 165 float exposure = 1.0f; 166 167 uint motionBlurSamples = 16; 168 uint motionBlurFramerate = 24; 169 float motionBlurRandomness = 0.2f; 170 float motionBlurMinDistance = 0.01f; 171 float motionBlurMaxDistance = 1.0f; 172 173 bool autofocus = true; 174 float focalDepth = 1.5; 175 float focalLength = 5.0; 176 float fStop = 2.0; 177 178 Texture colorLookupTable; 179 180 this(EventManager eventManager, Framebuffer inputBuffer, GBuffer gbuffer, Owner owner) 181 { 182 super(eventManager, owner); 183 184 this.inputBuffer = inputBuffer; 185 186 viewHalf = New!RenderView(0, 0, cast(uint)(view.width * glowViewScale), cast(uint)(view.height * glowViewScale), this); 187 188 ldrBuffer1 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA8, true, this); 189 ldrBuffer2 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA8, true, this); 190 ldrDoubleBuffer = New!DoubleBuffer(ldrBuffer1, ldrBuffer2, this); 191 192 hdrBuffer1 = New!Framebuffer(viewHalf.width, viewHalf.height, FrameBufferFormat.RGBA16F, true, this); 193 hdrBuffer2 = New!Framebuffer(viewHalf.width, viewHalf.height, FrameBufferFormat.RGBA16F, true, this); 194 195 hdrBuffer3 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA16F, true, this); 196 hdrBuffer4 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA16F, true, this); 197 198 dofShader = New!DepthOfFieldShader(this); 199 dofShader.gbuffer = gbuffer; 200 passDoF = New!FilterPass(pipeline, dofShader); 201 passDoF.view = view; 202 passDoF.inputBuffer = inputBuffer; 203 passDoF.outputBuffer = hdrBuffer3; 204 205 motionBlurShader = New!MotionBlurShader(this); 206 motionBlurShader.gbuffer = gbuffer; 207 passMotionBlur = New!FilterPass(pipeline, motionBlurShader); 208 passMotionBlur.view = view; 209 passMotionBlur.inputBuffer = passDoF.outputBuffer; 210 passMotionBlur.outputBuffer = hdrBuffer4; 211 212 brightPassShader = New!BrightPassShader(this); 213 brightPassShader.luminanceThreshold = glowThreshold; 214 passBrightPass = New!FilterPass(pipeline, brightPassShader); 215 passBrightPass.view = viewHalf; 216 passBrightPass.inputBuffer = passMotionBlur.outputBuffer; 217 passBrightPass.outputBuffer = hdrBuffer1; 218 219 passBlur = New!BlurPass(pipeline); 220 passBlur.view = viewHalf; 221 passBlur.inputBuffer = passBrightPass.outputBuffer; 222 passBlur.outputBuffer = hdrBuffer1; 223 passBlur.outputBuffer2 = hdrBuffer2; 224 passBlur.radius = glowRadius; 225 226 glowShader = New!GlowShader(this); 227 glowShader.blurredBuffer = passBlur.outputBuffer; 228 glowShader.intensity = glowIntensity; 229 passGlow = New!FilterPass(pipeline, glowShader); 230 passGlow.view = view; 231 passGlow.inputBuffer = passMotionBlur.outputBuffer; 232 passGlow.outputBuffer = hdrBuffer3; 233 234 tonemapShader = New!TonemapShader(this); 235 passTonemap = New!FilterPass(pipeline, tonemapShader); 236 passTonemap.view = view; 237 passTonemap.inputBuffer = passGlow.outputBuffer; 238 passTonemap.outputBuffer = ldrDoubleBuffer; 239 240 fxaaShader = New!FXAAShader(this); 241 passFXAA = New!FilterPass(pipeline, fxaaShader); 242 passFXAA.view = view; 243 passFXAA.inputBuffer = ldrDoubleBuffer; 244 passFXAA.outputBuffer = ldrDoubleBuffer; 245 246 lensDistortionShader = New!LensDistortionShader(this); 247 passLensDistortion = New!FilterPass(pipeline, lensDistortionShader); 248 passLensDistortion.view = view; 249 passLensDistortion.inputBuffer = ldrDoubleBuffer; 250 passLensDistortion.outputBuffer = ldrDoubleBuffer; 251 252 lutShader = New!LUTShader(this); 253 passLUT = New!FilterPass(pipeline, lutShader); 254 passLUT.view = view; 255 passLUT.inputBuffer = ldrDoubleBuffer; 256 passLUT.outputBuffer = ldrDoubleBuffer; 257 258 outputBuffer = ldrDoubleBuffer; 259 } 260 261 void depthOfFieldEnabled(bool mode) @property 262 { 263 _dofEnabled = mode; 264 passDoF.active = mode; 265 } 266 bool depthOfFieldEnabled() @property 267 { 268 return _dofEnabled; 269 } 270 271 void motionBlurEnabled(bool mode) @property 272 { 273 _motionBlurEnabled = mode; 274 passMotionBlur.active = mode; 275 } 276 bool motionBlurEnabled() @property 277 { 278 return _motionBlurEnabled; 279 } 280 281 void glowEnabled(bool mode) @property 282 { 283 _glowEnabled = mode; 284 passBrightPass.active = mode; 285 passBlur.active = mode; 286 passGlow.active = mode; 287 } 288 bool glowEnabled() @property 289 { 290 return _glowEnabled; 291 } 292 293 void fxaaEnabled(bool mode) @property 294 { 295 passFXAA.active = mode; 296 } 297 bool fxaaEnabled() @property 298 { 299 return passFXAA.active; 300 } 301 302 void lensDistortionEnabled(bool mode) @property 303 { 304 passLensDistortion.active = mode; 305 } 306 bool lensDistortionEnabled() @property 307 { 308 return passLensDistortion.active; 309 } 310 311 void lutEnabled(bool mode) @property 312 { 313 passLUT.active = mode; 314 } 315 bool lutEnabled() @property 316 { 317 return passLUT.active; 318 } 319 320 override void update(Time t) 321 { 322 super.update(t); 323 324 brightPassShader.luminanceThreshold = glowThreshold; 325 glowShader.intensity = glowIntensity; 326 passBlur.radius = glowRadius; 327 tonemapShader.tonemapper = tonemapper; 328 tonemapShader.exposure = exposure; 329 dofShader.autofocus = autofocus; 330 dofShader.focalDepth = focalDepth; 331 dofShader.focalLength = focalLength; 332 dofShader.fStop = fStop; 333 motionBlurShader.samples = motionBlurSamples; 334 motionBlurShader.currentFramerate = 60.0f; //1.0 / t.delta; 335 motionBlurShader.shutterFramerate = motionBlurFramerate; 336 motionBlurShader.offsetRandomCoefficient = motionBlurRandomness; 337 motionBlurShader.minDistance = motionBlurMinDistance; 338 motionBlurShader.maxDistance = motionBlurMaxDistance; 339 lutShader.colorLookupTable = colorLookupTable; 340 if (lutShader.colorLookupTable) 341 { 342 lutShader.colorLookupTable.useMipmapFiltering = false; 343 } 344 } 345 346 override void render() 347 { 348 if (outputBuffer) 349 outputBuffer.bind(); 350 351 if (!_dofEnabled) 352 { 353 passMotionBlur.inputBuffer = inputBuffer; 354 } 355 else 356 { 357 passMotionBlur.inputBuffer = passDoF.outputBuffer; 358 } 359 360 if (!_motionBlurEnabled) 361 { 362 if (_dofEnabled) 363 { 364 passBrightPass.inputBuffer = passDoF.outputBuffer; 365 passGlow.inputBuffer = passDoF.outputBuffer; 366 } 367 else 368 { 369 passBrightPass.inputBuffer = inputBuffer; 370 passGlow.inputBuffer = inputBuffer; 371 } 372 } 373 else 374 { 375 passBrightPass.inputBuffer = passMotionBlur.outputBuffer; 376 passGlow.inputBuffer = passMotionBlur.outputBuffer; 377 } 378 379 if (!_glowEnabled) 380 { 381 if (_motionBlurEnabled) 382 passTonemap.inputBuffer = passMotionBlur.outputBuffer; 383 else if (_dofEnabled) 384 passTonemap.inputBuffer = passDoF.outputBuffer; 385 else 386 passTonemap.inputBuffer = inputBuffer; 387 } 388 else 389 { 390 passTonemap.inputBuffer = passGlow.outputBuffer; 391 } 392 393 foreach(pass; pipeline.passes.data) 394 { 395 if (pass.active) 396 { 397 pass.render(); 398 ldrDoubleBuffer.swap(); 399 } 400 } 401 402 if (outputBuffer) 403 outputBuffer.unbind(); 404 } 405 406 override void setViewport(uint x, uint y, uint w, uint h) 407 { 408 super.setViewport(x, y, w, h); 409 410 viewHalf.resize(cast(uint)(view.width * glowViewScale), cast(uint)(view.height * glowViewScale)); 411 412 ldrBuffer1.resize(view.width, view.height); 413 ldrBuffer2.resize(view.width, view.height); 414 415 hdrBuffer1.resize(viewHalf.width, viewHalf.height); 416 hdrBuffer2.resize(viewHalf.width, viewHalf.height); 417 hdrBuffer3.resize(view.width, view.height); 418 hdrBuffer4.resize(view.width, view.height); 419 } 420 }