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