1 /* 2 Copyright (c) 2019-2022 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.view; 39 import dagon.render.framebuffer; 40 import dagon.render.gbuffer; 41 import dagon.postproc.filterpass; 42 import dagon.postproc.blurpass; 43 import dagon.postproc.presentpass; 44 import dagon.postproc.shaders.dof; 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 this.writeBuffer = writeBuffer; 65 this.readBuffer = readBuffer; 66 } 67 68 void swap() 69 { 70 auto w = writeBuffer; 71 writeBuffer = readBuffer; 72 readBuffer = w; 73 } 74 75 override GLuint colorTexture() 76 { 77 return readBuffer.colorTexture(); 78 } 79 80 override GLuint depthTexture() 81 { 82 return readBuffer.depthTexture(); 83 } 84 85 override void bind() 86 { 87 writeBuffer.bind(); 88 } 89 90 override void unbind() 91 { 92 writeBuffer.unbind(); 93 } 94 95 override void resize(uint width, uint height) 96 { 97 98 } 99 100 override void blitColorBuffer() 101 { 102 103 } 104 105 override void blitDepthBuffer() 106 { 107 108 } 109 } 110 111 class PostProcRenderer: Renderer 112 { 113 public: 114 115 Framebuffer inputBuffer; 116 Framebuffer outputBuffer; 117 118 protected: 119 120 DoubleBuffer ldrDoubleBuffer; 121 122 Framebuffer ldrBuffer1; 123 Framebuffer ldrBuffer2; 124 125 Framebuffer hdrBuffer1; 126 Framebuffer hdrBuffer2; 127 Framebuffer hdrBuffer3; 128 Framebuffer hdrBuffer4; 129 130 RenderView viewHalf; 131 BlurPass passBlur; 132 133 DepthOfFieldShader dofShader; 134 BrightPassShader brightPassShader; 135 GlowShader glowShader; 136 MotionBlurShader motionBlurShader; 137 TonemapShader tonemapShader; 138 FXAAShader fxaaShader; 139 LensDistortionShader lensDistortionShader; 140 LUTShader lutShader; 141 142 FilterPass passDoF; 143 FilterPass passMotionBlur; 144 FilterPass passBrightPass; 145 FilterPass passGlow; 146 FilterPass passTonemap; 147 FilterPass passFXAA; 148 FilterPass passLensDistortion; 149 FilterPass passLUT; 150 PresentPass passPresent; 151 152 bool _dofEnabled = false; 153 bool _motionBlurEnabled = false; 154 bool _glowEnabled = false; 155 156 public: 157 158 float glowViewScale = 0.33f; 159 160 float glowThreshold = 0.8f; 161 float glowIntensity = 0.2f; 162 int glowRadius = 5; 163 Tonemapper tonemapper = Tonemapper.ACES; 164 float exposure = 1.0f; 165 166 uint motionBlurSamples = 16; 167 uint motionBlurFramerate = 24; 168 float motionBlurRandomness = 0.2f; 169 float motionBlurMinDistance = 0.01f; 170 float motionBlurMaxDistance = 1.0f; 171 float radialBlurAmount = 0.0f; 172 173 float lensDistortionScale = 1.0f; 174 float lensDistortionDispersion = 0.1f; 175 176 bool autofocus = true; 177 float focalDepth = 1.5; 178 float focalLength = 5.0; 179 float fStop = 2.0; 180 181 bool dofManual = false; 182 float dofNearStart = 1.0; 183 float dofNearDistance = 2.0; 184 float dofFarStart = 1.0; 185 float dofFarDistance = 3.0; 186 187 Texture colorLookupTable; 188 189 this(EventManager eventManager, Framebuffer inputBuffer, GBuffer gbuffer, Owner owner) 190 { 191 super(eventManager, owner); 192 193 this.inputBuffer = inputBuffer; 194 195 viewHalf = New!RenderView(0, 0, cast(uint)(view.width * glowViewScale), cast(uint)(view.height * glowViewScale), this); 196 197 ldrBuffer1 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA8, true, this); 198 ldrBuffer2 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA8, true, this); 199 ldrDoubleBuffer = New!DoubleBuffer(ldrBuffer1, ldrBuffer2, this); 200 201 hdrBuffer1 = New!Framebuffer(viewHalf.width, viewHalf.height, FrameBufferFormat.RGBA16F, true, this); 202 hdrBuffer2 = New!Framebuffer(viewHalf.width, viewHalf.height, FrameBufferFormat.RGBA16F, true, this); 203 204 hdrBuffer3 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA16F, true, this); 205 hdrBuffer4 = New!Framebuffer(view.width, view.height, FrameBufferFormat.RGBA16F, true, this); 206 207 dofShader = New!DepthOfFieldShader(this); 208 dofShader.gbuffer = gbuffer; 209 passDoF = New!FilterPass(pipeline, dofShader); 210 passDoF.view = view; 211 passDoF.inputBuffer = inputBuffer; 212 passDoF.outputBuffer = hdrBuffer3; 213 214 motionBlurShader = New!MotionBlurShader(this); 215 motionBlurShader.gbuffer = gbuffer; 216 passMotionBlur = New!FilterPass(pipeline, motionBlurShader); 217 passMotionBlur.view = view; 218 passMotionBlur.inputBuffer = passDoF.outputBuffer; 219 passMotionBlur.outputBuffer = hdrBuffer4; 220 221 brightPassShader = New!BrightPassShader(this); 222 brightPassShader.luminanceThreshold = glowThreshold; 223 passBrightPass = New!FilterPass(pipeline, brightPassShader); 224 passBrightPass.view = viewHalf; 225 passBrightPass.inputBuffer = passMotionBlur.outputBuffer; 226 passBrightPass.outputBuffer = hdrBuffer1; 227 228 passBlur = New!BlurPass(pipeline); 229 passBlur.view = viewHalf; 230 passBlur.inputBuffer = passBrightPass.outputBuffer; 231 passBlur.outputBuffer = hdrBuffer1; 232 passBlur.outputBuffer2 = hdrBuffer2; 233 passBlur.radius = glowRadius; 234 235 glowShader = New!GlowShader(this); 236 glowShader.blurredBuffer = passBlur.outputBuffer; 237 glowShader.intensity = glowIntensity; 238 passGlow = New!FilterPass(pipeline, glowShader); 239 passGlow.view = view; 240 passGlow.inputBuffer = passMotionBlur.outputBuffer; 241 passGlow.outputBuffer = hdrBuffer3; 242 243 tonemapShader = New!TonemapShader(this); 244 passTonemap = New!FilterPass(pipeline, tonemapShader); 245 passTonemap.view = view; 246 passTonemap.inputBuffer = passGlow.outputBuffer; 247 passTonemap.outputBuffer = ldrDoubleBuffer; 248 249 fxaaShader = New!FXAAShader(this); 250 passFXAA = New!FilterPass(pipeline, fxaaShader); 251 passFXAA.view = view; 252 passFXAA.inputBuffer = ldrDoubleBuffer; 253 passFXAA.outputBuffer = ldrDoubleBuffer; 254 255 lensDistortionShader = New!LensDistortionShader(this); 256 passLensDistortion = New!FilterPass(pipeline, lensDistortionShader); 257 passLensDistortion.view = view; 258 passLensDistortion.inputBuffer = ldrDoubleBuffer; 259 passLensDistortion.outputBuffer = ldrDoubleBuffer; 260 261 lutShader = New!LUTShader(this); 262 passLUT = New!FilterPass(pipeline, lutShader); 263 passLUT.view = view; 264 passLUT.inputBuffer = ldrDoubleBuffer; 265 passLUT.outputBuffer = ldrDoubleBuffer; 266 267 outputBuffer = ldrDoubleBuffer; 268 } 269 270 void depthOfFieldEnabled(bool mode) @property 271 { 272 _dofEnabled = mode; 273 passDoF.active = mode; 274 } 275 bool depthOfFieldEnabled() @property 276 { 277 return _dofEnabled; 278 } 279 280 void motionBlurEnabled(bool mode) @property 281 { 282 _motionBlurEnabled = mode; 283 passMotionBlur.active = mode; 284 } 285 bool motionBlurEnabled() @property 286 { 287 return _motionBlurEnabled; 288 } 289 290 void glowEnabled(bool mode) @property 291 { 292 _glowEnabled = mode; 293 passBrightPass.active = mode; 294 passBlur.active = mode; 295 passGlow.active = mode; 296 } 297 bool glowEnabled() @property 298 { 299 return _glowEnabled; 300 } 301 302 void fxaaEnabled(bool mode) @property 303 { 304 passFXAA.active = mode; 305 } 306 bool fxaaEnabled() @property 307 { 308 return passFXAA.active; 309 } 310 311 void lensDistortionEnabled(bool mode) @property 312 { 313 passLensDistortion.active = mode; 314 } 315 bool lensDistortionEnabled() @property 316 { 317 return passLensDistortion.active; 318 } 319 320 void lutEnabled(bool mode) @property 321 { 322 passLUT.active = mode; 323 } 324 bool lutEnabled() @property 325 { 326 return passLUT.active; 327 } 328 329 override void update(Time t) 330 { 331 super.update(t); 332 333 brightPassShader.luminanceThreshold = glowThreshold; 334 glowShader.intensity = glowIntensity; 335 passBlur.radius = glowRadius; 336 337 tonemapShader.tonemapper = tonemapper; 338 tonemapShader.exposure = exposure; 339 340 dofShader.autofocus = autofocus; 341 dofShader.focalDepth = focalDepth; 342 dofShader.focalLength = focalLength; 343 dofShader.fStop = fStop; 344 dofShader.manual = dofManual; 345 dofShader.nearStart = dofNearStart; 346 dofShader.nearDistance = dofNearDistance; 347 dofShader.farStart = dofFarStart; 348 dofShader.farDistance = dofFarDistance; 349 350 motionBlurShader.samples = motionBlurSamples; 351 motionBlurShader.currentFramerate = 60.0f; //1.0 / t.delta; 352 motionBlurShader.shutterFramerate = motionBlurFramerate; 353 motionBlurShader.offsetRandomCoefficient = motionBlurRandomness; 354 motionBlurShader.minDistance = motionBlurMinDistance; 355 motionBlurShader.maxDistance = motionBlurMaxDistance; 356 motionBlurShader.radialBlur = radialBlurAmount; 357 358 lensDistortionShader.scale = lensDistortionScale; 359 lensDistortionShader.dispersion = lensDistortionDispersion; 360 361 lutShader.colorLookupTable = colorLookupTable; 362 if (lutShader.colorLookupTable) 363 { 364 lutShader.colorLookupTable.useMipmapFiltering = false; 365 } 366 } 367 368 override void render() 369 { 370 if (outputBuffer) 371 outputBuffer.bind(); 372 373 if (!_dofEnabled) 374 { 375 passMotionBlur.inputBuffer = inputBuffer; 376 } 377 else 378 { 379 passMotionBlur.inputBuffer = passDoF.outputBuffer; 380 } 381 382 if (!_motionBlurEnabled) 383 { 384 if (_dofEnabled) 385 { 386 passBrightPass.inputBuffer = passDoF.outputBuffer; 387 passGlow.inputBuffer = passDoF.outputBuffer; 388 } 389 else 390 { 391 passBrightPass.inputBuffer = inputBuffer; 392 passGlow.inputBuffer = inputBuffer; 393 } 394 } 395 else 396 { 397 passBrightPass.inputBuffer = passMotionBlur.outputBuffer; 398 passGlow.inputBuffer = passMotionBlur.outputBuffer; 399 } 400 401 if (!_glowEnabled) 402 { 403 if (_motionBlurEnabled) 404 passTonemap.inputBuffer = passMotionBlur.outputBuffer; 405 else if (_dofEnabled) 406 passTonemap.inputBuffer = passDoF.outputBuffer; 407 else 408 passTonemap.inputBuffer = inputBuffer; 409 } 410 else 411 { 412 passTonemap.inputBuffer = passGlow.outputBuffer; 413 } 414 415 foreach(pass; pipeline.passes.data) 416 { 417 if (pass.active) 418 { 419 pass.render(); 420 ldrDoubleBuffer.swap(); 421 } 422 } 423 424 if (outputBuffer) 425 outputBuffer.unbind(); 426 } 427 428 override void setViewport(uint x, uint y, uint w, uint h) 429 { 430 super.setViewport(x, y, w, h); 431 432 viewHalf.resize(cast(uint)(view.width * glowViewScale), cast(uint)(view.height * glowViewScale)); 433 434 ldrBuffer1.resize(view.width, view.height); 435 ldrBuffer2.resize(view.width, view.height); 436 437 hdrBuffer1.resize(viewHalf.width, viewHalf.height); 438 hdrBuffer2.resize(viewHalf.width, viewHalf.height); 439 hdrBuffer3.resize(view.width, view.height); 440 hdrBuffer4.resize(view.width, view.height); 441 } 442 }