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.deferredrenderer; 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.resource.scene; 36 import dagon.render.deferred; 37 import dagon.render.gbuffer; 38 import dagon.render.view; 39 import dagon.render.framebuffer; 40 import dagon.render.shadowpass; 41 import dagon.postproc.filterpass; 42 import dagon.postproc.shaders.denoise; 43 import dagon.game.renderer; 44 45 class DeferredRenderer: Renderer 46 { 47 GBuffer gbuffer; 48 49 DenoiseShader denoiseShader; 50 51 ShadowPass passShadow; 52 DeferredClearPass passClear; 53 DeferredBackgroundPass passBackground; 54 DeferredGeometryPass passStaticGeometry; 55 DeferredDecalPass passDecals; 56 DeferredGeometryPass passDynamicGeometry; 57 DeferredOcclusionPass passOcclusion; 58 FilterPass passOcclusionDenoise; 59 DeferredEnvironmentPass passEnvironment; 60 DeferredLightPass passLight; 61 DeferredParticlesPass passParticles; 62 DeferredForwardPass passForward; 63 DeferredDebugOutputPass passDebug; 64 65 RenderView occlusionView; 66 Framebuffer occlusionNoisyBuffer; 67 Framebuffer occlusionBuffer; 68 69 DebugOutputMode outputMode = DebugOutputMode.Radiance; 70 71 bool _ssaoEnabled = true; 72 73 int ssaoSamples = 10; 74 float ssaoRadius = 0.2f; 75 float ssaoPower = 7.0f; 76 float ssaoDenoise = 1.0f; 77 78 this(EventManager eventManager, Owner owner) 79 { 80 super(eventManager, owner); 81 82 occlusionView = New!RenderView(0, 0, view.width / 2, view.height / 2, this); 83 occlusionNoisyBuffer = New!Framebuffer(occlusionView.width, occlusionView.height, FrameBufferFormat.R8, false, this); 84 occlusionBuffer = New!Framebuffer(occlusionView.width, occlusionView.height, FrameBufferFormat.R8, false, this); 85 86 // HDR buffer 87 auto radianceBuffer = New!Framebuffer(eventManager.windowWidth, eventManager.windowHeight, FrameBufferFormat.RGBA16F, true, this); 88 outputBuffer = radianceBuffer; 89 90 gbuffer = New!GBuffer(view.width, view.height, radianceBuffer, this); 91 92 passShadow = New!ShadowPass(pipeline); 93 94 passClear = New!DeferredClearPass(pipeline, gbuffer); 95 96 passBackground = New!DeferredBackgroundPass(pipeline, gbuffer); 97 passBackground.view = view; 98 99 passStaticGeometry = New!DeferredGeometryPass(pipeline, gbuffer); 100 passStaticGeometry.view = view; 101 102 passDecals = New!DeferredDecalPass(pipeline, gbuffer); 103 passDecals.view = view; 104 105 passDynamicGeometry = New!DeferredGeometryPass(pipeline, gbuffer); 106 passDynamicGeometry.view = view; 107 108 passOcclusion = New!DeferredOcclusionPass(pipeline, gbuffer); 109 passOcclusion.view = occlusionView; 110 passOcclusion.outputBuffer = occlusionNoisyBuffer; 111 112 denoiseShader = New!DenoiseShader(this); 113 passOcclusionDenoise = New!FilterPass(pipeline, denoiseShader); 114 passOcclusionDenoise.view = occlusionView; 115 passOcclusionDenoise.inputBuffer = occlusionNoisyBuffer; 116 passOcclusionDenoise.outputBuffer = occlusionBuffer; 117 118 passEnvironment = New!DeferredEnvironmentPass(pipeline, gbuffer); 119 passEnvironment.view = view; 120 passEnvironment.outputBuffer = radianceBuffer; 121 passEnvironment.occlusionBuffer = occlusionBuffer; 122 123 passLight = New!DeferredLightPass(pipeline, gbuffer); 124 passLight.view = view; 125 passLight.outputBuffer = radianceBuffer; 126 passLight.occlusionBuffer = occlusionBuffer; 127 128 passForward = New!DeferredForwardPass(pipeline, gbuffer); 129 passForward.view = view; 130 passForward.outputBuffer = radianceBuffer; 131 132 passParticles = New!DeferredParticlesPass(pipeline, gbuffer); 133 passParticles.view = view; 134 passParticles.outputBuffer = radianceBuffer; 135 passParticles.gbuffer = gbuffer; 136 137 passDebug = New!DeferredDebugOutputPass(pipeline, gbuffer); 138 passDebug.view = view; 139 passDebug.active = false; 140 passDebug.outputBuffer = radianceBuffer; 141 passDebug.occlusionBuffer = occlusionBuffer; 142 } 143 144 void ssaoEnabled(bool mode) @property 145 { 146 _ssaoEnabled = mode; 147 passOcclusion.active = mode; 148 passOcclusionDenoise.active = mode; 149 if (_ssaoEnabled) 150 { 151 passEnvironment.occlusionBuffer = occlusionBuffer; 152 passLight.occlusionBuffer = occlusionBuffer; 153 } 154 else 155 { 156 passEnvironment.occlusionBuffer = null; 157 passLight.occlusionBuffer = null; 158 } 159 } 160 161 bool ssaoEnabled() @property 162 { 163 return _ssaoEnabled; 164 } 165 166 override void scene(Scene s) 167 { 168 passShadow.group = s.spatial; 169 passShadow.lightGroup = s.lights; 170 passBackground.group = s.background; 171 passStaticGeometry.group = s.spatialOpaqueStatic; 172 passDecals.group = s.decals; 173 passDynamicGeometry.group = s.spatialOpaqueDynamic; 174 passLight.groupSunLights = s.sunLights; 175 passLight.groupAreaLights = s.areaLights; 176 passForward.group = s.spatialTransparent; 177 passParticles.group = s.spatial; 178 179 passBackground.state.environment = s.environment; 180 passStaticGeometry.state.environment = s.environment; 181 passDecals.state.environment = s.environment; 182 passDynamicGeometry.state.environment = s.environment; 183 passEnvironment.state.environment = s.environment; 184 passLight.state.environment = s.environment; 185 passForward.state.environment = s.environment; 186 passParticles.state.environment = s.environment; 187 passDebug.state.environment = s.environment; 188 } 189 190 override void update(Time t) 191 { 192 passShadow.camera = activeCamera; 193 passDebug.active = (outputMode != DebugOutputMode.Radiance); 194 passDebug.outputMode = outputMode; 195 196 passOcclusion.ssaoShader.samples = ssaoSamples; 197 passOcclusion.ssaoShader.radius = ssaoRadius; 198 passOcclusion.ssaoShader.power = ssaoPower; 199 denoiseShader.factor = ssaoDenoise; 200 201 super.update(t); 202 } 203 204 override void setViewport(uint x, uint y, uint w, uint h) 205 { 206 super.setViewport(x, y, w, h); 207 208 outputBuffer.resize(view.width, view.height); 209 gbuffer.resize(view.width, view.height); 210 211 occlusionView.resize(view.width / 2, view.height / 2); 212 occlusionNoisyBuffer.resize(occlusionView.width, occlusionView.height); 213 occlusionBuffer.resize(occlusionView.width, occlusionView.height); 214 } 215 }