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 }