@@ -75,12 +75,242 @@ namespace cage
7575
7676 void screenSpaceAmbientOcclusion (const ScreenSpaceAmbientOcclusionConfig &config)
7777 {
78- // todo
78+ static constexpr int downscale = 3 ;
79+
80+ GraphicsEncoder *q = config.encoder ;
81+ GraphicsDevice *d = q->getDevice ();
82+
83+ Holder<Model> model = config.assets ->get <Model>(HashString (" cage/models/square.obj" ));
84+
85+ // prepare
86+
87+ const Vec2i res = max (config.resolution / downscale, 1u );
88+ Holder<Texture> depthLowRes = [&]()
89+ {
90+ wgpu::TextureDescriptor desc = {};
91+ desc.size .width = res[0 ];
92+ desc.size .height = res[1 ];
93+ desc.format = wgpu::TextureFormat::R32Float;
94+ desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
95+ desc.label = " ssao depth target" ;
96+ wgpu::Texture tex = d->nativeDevice ()->CreateTexture (&desc);
97+ wgpu::Sampler samp = d->nativeDevice ()->CreateSampler ();
98+ return newTexture (tex, tex.CreateView (), samp, " ssao depth target" );
99+ }();
100+ Holder<Texture> ssaoLowRes = [&]()
101+ {
102+ wgpu::TextureDescriptor desc = {};
103+ desc.size .width = res[0 ];
104+ desc.size .height = res[1 ];
105+ desc.format = wgpu::TextureFormat::R16Float;
106+ desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
107+ desc.label = " ssao lowres target" ;
108+ wgpu::Texture tex = d->nativeDevice ()->CreateTexture (&desc);
109+ wgpu::Sampler samp = d->nativeDevice ()->CreateSampler ();
110+ return newTexture (tex, tex.CreateView (), samp, " ssao lowres target" );
111+ }();
112+
113+ struct Shader
114+ {
115+ Mat4 proj;
116+ Mat4 projInv;
117+ Vec4 params; // strength, bias, power, raysLength
118+ Vec4i iparams; // sampleCount, hashSeed
119+ } s;
120+ s.proj = config.proj ;
121+ s.projInv = inverse (config.proj );
122+ s.params = Vec4 (config.strength , config.bias , config.power , config.raysLength );
123+ s.iparams [0 ] = config.samplesCount ;
124+ s.iparams [1 ] = hash (config.frameIndex );
125+ Holder<GpuBuffer> buff = newGpuBufferUniform (config.encoder ->getDevice (), " UniSsao" );
126+ buff->write (s);
127+
128+ Holder<GpuBuffer> buffPoints = newGpuBufferUniform (config.encoder ->getDevice (), " SsaoPoints" );
129+ buffPoints->write (privat::pointsForSsaoShader (config.samplesCount ));
130+
131+ { // low-res depth
132+ PassConfig pass;
133+ pass.colorTargets .push_back ({ +depthLowRes });
134+ q->nextPass (pass);
135+ const auto scope = config.encoder ->namedScope (" ssao depth" );
136+
137+ BindingsCreateConfig bind;
138+ bind.textures .push_back ({ config.inDepth , 0 });
139+
140+ Holder<MultiShader> ms = config.assets ->get <MultiShader>(HashString (" cage/shaders/effects/ssaoDownscaleDepth.glsl" ));
141+
142+ DrawConfig draw;
143+ draw.bindings = newGpuBindings (d, bind);
144+ draw.model = +model;
145+ draw.shader = +ms->get (0 );
146+ q->draw (draw);
147+ }
148+
149+ { // generate
150+ PassConfig pass;
151+ pass.colorTargets .push_back ({ +ssaoLowRes });
152+ q->nextPass (pass);
153+ const auto scope = config.encoder ->namedScope (" ssao generate" );
154+
155+ BindingsCreateConfig bind;
156+ bind.buffers .push_back ({ +buff, 0 });
157+ bind.buffers .push_back ({ +buffPoints, 1 });
158+ bind.textures .push_back ({ +depthLowRes, 2 });
159+
160+ Holder<MultiShader> ms = config.assets ->get <MultiShader>(HashString (" cage/shaders/effects/ssaoGenerate.glsl" ));
161+
162+ DrawConfig draw;
163+ draw.bindings = newGpuBindings (d, bind);
164+ draw.model = +model;
165+ draw.shader = +ms->get (0 );
166+ q->draw (draw);
167+ }
168+
169+ { // blur
170+ Holder<Texture> tmp = [&]()
171+ {
172+ wgpu::TextureDescriptor desc = {};
173+ desc.size .width = res[0 ];
174+ desc.size .height = res[1 ];
175+ desc.format = wgpu::TextureFormat::R16Float;
176+ desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
177+ desc.label = " ssao blur temporary" ;
178+ wgpu::Texture tex = d->nativeDevice ()->CreateTexture (&desc);
179+ return newTexture (tex, tex.CreateView (), d->nativeDevice ()->CreateSampler (), " ssao blur temporary" );
180+ }();
181+
182+ GaussianBlurConfig gb;
183+ (ScreenSpaceCommonConfig &)gb = config;
184+ gb.inTex = +ssaoLowRes;
185+ gb.tmpTex = +tmp;
186+ for (uint32 i = 0 ; i < config.blurPasses ; i++)
187+ gaussianBlur (gb);
188+ }
189+
190+ { // resolve
191+ PassConfig pass;
192+ pass.colorTargets .push_back ({ +config.outAo });
193+ q->nextPass (pass);
194+ const auto scope = config.encoder ->namedScope (" ssao resolve" );
195+
196+ BindingsCreateConfig bind;
197+ bind.buffers .push_back ({ +buff, 0 });
198+ bind.textures .push_back ({ +ssaoLowRes, 1 });
199+
200+ Holder<MultiShader> ms = config.assets ->get <MultiShader>(HashString (" cage/shaders/effects/ssaoResolve.glsl" ));
201+
202+ DrawConfig draw;
203+ draw.bindings = newGpuBindings (d, bind);
204+ draw.model = +model;
205+ draw.shader = +ms->get (0 );
206+ q->draw (draw);
207+ }
79208 }
80209
81210 void screenSpaceDepthOfField (const ScreenSpaceDepthOfFieldConfig &config)
82211 {
83- // todo
212+ static constexpr int downscale = 3 ;
213+
214+ GraphicsEncoder *q = config.encoder ;
215+ GraphicsDevice *d = q->getDevice ();
216+
217+ Holder<Model> model = config.assets ->get <Model>(HashString (" cage/models/square.obj" ));
218+
219+ // prepare
220+
221+ const Vec2i res = max (config.resolution / downscale, 1u );
222+ Holder<Texture> texDof = [&]()
223+ {
224+ wgpu::TextureDescriptor desc = {};
225+ desc.size .width = res[0 ];
226+ desc.size .height = res[1 ];
227+ desc.format = wgpu::TextureFormat::RGBA16Float;
228+ desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
229+ desc.label = " dof color target" ;
230+ wgpu::Texture tex = d->nativeDevice ()->CreateTexture (&desc);
231+ wgpu::SamplerDescriptor sd = {};
232+ sd.addressModeU = sd.addressModeV = sd.addressModeW = wgpu::AddressMode::ClampToEdge;
233+ sd.magFilter = sd.minFilter = wgpu::FilterMode::Linear;
234+ sd.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
235+ sd.label = " dof color sampler" ;
236+ wgpu::Sampler samp = d->nativeDevice ()->CreateSampler (&sd);
237+ return newTexture (tex, tex.CreateView (), samp, " dof color target" );
238+ }();
239+
240+ struct Shader
241+ {
242+ Mat4 projInv;
243+ Vec4 dofNear; // near, far
244+ Vec4 dofFar; // near, far
245+ } s;
246+ const Real fd = config.focusDistance ;
247+ const Real fr = config.focusRadius ;
248+ const Real br = config.blendRadius ;
249+ s.projInv = inverse (config.proj );
250+ s.dofNear = Vec4 (fd - fr - br, fd - fr, 0 , 0 );
251+ s.dofFar = Vec4 (fd + fr, fd + fr + br, 0 , 0 );
252+ Holder<GpuBuffer> buff = newGpuBufferUniform (config.encoder ->getDevice (), " UniDof" );
253+ buff->write (s);
254+
255+ { // collect
256+ PassConfig pass;
257+ pass.colorTargets .push_back ({ +texDof });
258+ q->nextPass (pass);
259+ const auto scope = config.encoder ->namedScope (" dof collect" );
260+
261+ BindingsCreateConfig bind;
262+ bind.textures .push_back ({ config.inColor , 0 });
263+
264+ Holder<MultiShader> ms = config.assets ->get <MultiShader>(HashString (" cage/shaders/effects/dofCollect.glsl" ));
265+
266+ DrawConfig draw;
267+ draw.bindings = newGpuBindings (d, bind);
268+ draw.model = +model;
269+ draw.shader = +ms->get (0 );
270+ q->draw (draw);
271+ }
272+
273+ { // blur
274+ Holder<Texture> tmp = [&]()
275+ {
276+ wgpu::TextureDescriptor desc = {};
277+ desc.size .width = res[0 ];
278+ desc.size .height = res[1 ];
279+ desc.format = wgpu::TextureFormat::RGBA16Float;
280+ desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
281+ desc.label = " dof blur temporary" ;
282+ wgpu::Texture tex = d->nativeDevice ()->CreateTexture (&desc);
283+ return newTexture (tex, tex.CreateView (), d->nativeDevice ()->CreateSampler (), " dof blur temporary" );
284+ }();
285+
286+ GaussianBlurConfig gb;
287+ (ScreenSpaceCommonConfig &)gb = config;
288+ gb.inTex = +texDof;
289+ gb.tmpTex = +tmp;
290+ for (uint32 i = 0 ; i < config.blurPasses ; i++)
291+ gaussianBlur (gb);
292+ }
293+
294+ { // apply
295+ PassConfig pass;
296+ pass.colorTargets .push_back ({ +config.outColor });
297+ q->nextPass (pass);
298+ const auto scope = config.encoder ->namedScope (" dof apply" );
299+
300+ BindingsCreateConfig bind;
301+ bind.buffers .push_back ({ +buff, 0 });
302+ bind.textures .push_back ({ config.inColor , 1 });
303+ bind.textures .push_back ({ config.inDepth , 3 });
304+ bind.textures .push_back ({ +texDof, 5 });
305+
306+ Holder<MultiShader> ms = config.assets ->get <MultiShader>(HashString (" cage/shaders/effects/dofApply.glsl" ));
307+
308+ DrawConfig draw;
309+ draw.bindings = newGpuBindings (d, bind);
310+ draw.model = +model;
311+ draw.shader = +ms->get (0 );
312+ q->draw (draw);
313+ }
84314 }
85315
86316 void screenSpaceBloom (const ScreenSpaceBloomConfig &config)
0 commit comments