1/**************************************************************************/
2/* ss_effects.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "ss_effects.h"
32
33#include "core/config/project_settings.h"
34#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
35#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
36#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
37#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
38
39using namespace RendererRD;
40
41SSEffects *SSEffects::singleton = nullptr;
42
43static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
44 for (int i = 0; i < 4; i++) {
45 for (int j = 0; j < 4; j++) {
46 p_array[i * 4 + j] = p_mtx.columns[i][j];
47 }
48 }
49}
50
51SSEffects::SSEffects() {
52 singleton = this;
53
54 // Initialize depth buffer for screen space effects
55 {
56 Vector<String> downsampler_modes;
57 downsampler_modes.push_back("\n");
58 downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
59 downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
60 downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
61 downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
62 downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
63 downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
64
65 ss_effects.downsample_shader.initialize(downsampler_modes);
66
67 ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
68
69 for (int i = 0; i < SS_EFFECTS_MAX; i++) {
70 ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
71 }
72
73 ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
74 SSEffectsGatherConstants gather_constants;
75
76 const int sub_pass_count = 5;
77 for (int pass = 0; pass < 4; pass++) {
78 for (int subPass = 0; subPass < sub_pass_count; subPass++) {
79 int a = pass;
80
81 int spmap[5]{ 0, 1, 4, 3, 2 };
82 int b = spmap[subPass];
83
84 float ca, sa;
85 float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
86
87 ca = Math::cos(angle0);
88 sa = Math::sin(angle0);
89
90 float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;
91
92 gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;
93 gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;
94 gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;
95 gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;
96 }
97 }
98
99 RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
100 }
101
102 // Initialize Screen Space Indirect Lighting (SSIL)
103 ssil_set_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to"));
104
105 {
106 Vector<String> ssil_modes;
107 ssil_modes.push_back("\n");
108 ssil_modes.push_back("\n#define SSIL_BASE\n");
109 ssil_modes.push_back("\n#define ADAPTIVE\n");
110
111 ssil.gather_shader.initialize(ssil_modes);
112
113 ssil.gather_shader_version = ssil.gather_shader.version_create();
114
115 for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
116 ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
117 }
118 ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
119 }
120
121 {
122 Vector<String> ssil_modes;
123 ssil_modes.push_back("\n#define GENERATE_MAP\n");
124 ssil_modes.push_back("\n#define PROCESS_MAPA\n");
125 ssil_modes.push_back("\n#define PROCESS_MAPB\n");
126
127 ssil.importance_map_shader.initialize(ssil_modes);
128
129 ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
130
131 for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
132 ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
133 }
134 ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
135 int zero[1] = { 0 };
136 RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
137 RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
138
139 Vector<RD::Uniform> uniforms;
140 {
141 RD::Uniform u;
142 u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
143 u.binding = 0;
144 u.append_id(ssil.importance_map_load_counter);
145 uniforms.push_back(u);
146 }
147 ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
148 RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
149 }
150
151 {
152 Vector<String> ssil_modes;
153 ssil_modes.push_back("\n#define MODE_NON_SMART\n");
154 ssil_modes.push_back("\n#define MODE_SMART\n");
155 ssil_modes.push_back("\n#define MODE_WIDE\n");
156
157 ssil.blur_shader.initialize(ssil_modes);
158
159 ssil.blur_shader_version = ssil.blur_shader.version_create();
160 for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
161 ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
162 }
163 }
164
165 {
166 Vector<String> ssil_modes;
167 ssil_modes.push_back("\n#define MODE_NON_SMART\n");
168 ssil_modes.push_back("\n#define MODE_SMART\n");
169 ssil_modes.push_back("\n#define MODE_HALF\n");
170
171 ssil.interleave_shader.initialize(ssil_modes);
172
173 ssil.interleave_shader_version = ssil.interleave_shader.version_create();
174 for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
175 ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
176 }
177 }
178
179 // Initialize Screen Space Ambient Occlusion (SSAO)
180 ssao_set_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
181
182 {
183 RD::SamplerState sampler;
184 sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
185 sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
186 sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
187 sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
188 sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
189 sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
190 sampler.max_lod = 4;
191
192 uint32_t pipeline = 0;
193 {
194 Vector<String> ssao_modes;
195
196 ssao_modes.push_back("\n");
197 ssao_modes.push_back("\n#define SSAO_BASE\n");
198 ssao_modes.push_back("\n#define ADAPTIVE\n");
199
200 ssao.gather_shader.initialize(ssao_modes);
201
202 ssao.gather_shader_version = ssao.gather_shader.version_create();
203
204 for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
205 ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
206 pipeline++;
207 }
208 }
209
210 {
211 Vector<String> ssao_modes;
212 ssao_modes.push_back("\n#define GENERATE_MAP\n");
213 ssao_modes.push_back("\n#define PROCESS_MAPA\n");
214 ssao_modes.push_back("\n#define PROCESS_MAPB\n");
215
216 ssao.importance_map_shader.initialize(ssao_modes);
217
218 ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
219
220 for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
221 ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
222
223 pipeline++;
224 }
225
226 ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
227 int zero[1] = { 0 };
228 RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
229 RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
230
231 Vector<RD::Uniform> uniforms;
232 {
233 RD::Uniform u;
234 u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
235 u.binding = 0;
236 u.append_id(ssao.importance_map_load_counter);
237 uniforms.push_back(u);
238 }
239 ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
240 RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
241 }
242
243 {
244 Vector<String> ssao_modes;
245 ssao_modes.push_back("\n#define MODE_NON_SMART\n");
246 ssao_modes.push_back("\n#define MODE_SMART\n");
247 ssao_modes.push_back("\n#define MODE_WIDE\n");
248
249 ssao.blur_shader.initialize(ssao_modes);
250
251 ssao.blur_shader_version = ssao.blur_shader.version_create();
252
253 for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
254 ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
255
256 pipeline++;
257 }
258 }
259
260 {
261 Vector<String> ssao_modes;
262 ssao_modes.push_back("\n#define MODE_NON_SMART\n");
263 ssao_modes.push_back("\n#define MODE_SMART\n");
264 ssao_modes.push_back("\n#define MODE_HALF\n");
265
266 ssao.interleave_shader.initialize(ssao_modes);
267
268 ssao.interleave_shader_version = ssao.interleave_shader.version_create();
269 for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
270 ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
271 RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
272 pipeline++;
273 }
274 }
275
276 ERR_FAIL_COND(pipeline != SSAO_MAX);
277
278 ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
279 }
280
281 // Screen Space Reflections
282 ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality")));
283
284 {
285 Vector<RD::PipelineSpecializationConstant> specialization_constants;
286
287 {
288 RD::PipelineSpecializationConstant sc;
289 sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
290 sc.constant_id = 0; // SSR_USE_FULL_PROJECTION_MATRIX
291 sc.bool_value = false;
292 specialization_constants.push_back(sc);
293 }
294
295 {
296 Vector<String> ssr_scale_modes;
297 ssr_scale_modes.push_back("\n");
298
299 ssr_scale.shader.initialize(ssr_scale_modes);
300 ssr_scale.shader_version = ssr_scale.shader.version_create();
301
302 for (int v = 0; v < SSR_VARIATIONS; v++) {
303 specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
304 ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants);
305 }
306 }
307
308 {
309 Vector<String> ssr_modes;
310 ssr_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_NORMAL
311 ssr_modes.push_back("\n#define MODE_ROUGH\n"); // SCREEN_SPACE_REFLECTION_ROUGH
312
313 ssr.shader.initialize(ssr_modes);
314 ssr.shader_version = ssr.shader.version_create();
315
316 for (int v = 0; v < SSR_VARIATIONS; v++) {
317 specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
318 for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
319 ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants);
320 }
321 }
322 }
323
324 {
325 Vector<String> ssr_filter_modes;
326 ssr_filter_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL
327 ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); // SCREEN_SPACE_REFLECTION_FILTER_VERTICAL
328
329 ssr_filter.shader.initialize(ssr_filter_modes);
330 ssr_filter.shader_version = ssr_filter.shader.version_create();
331
332 for (int v = 0; v < SSR_VARIATIONS; v++) {
333 specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
334 for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
335 ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants);
336 }
337 }
338 }
339 }
340
341 // Subsurface scattering
342 sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
343 sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
344 sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
345
346 {
347 Vector<String> sss_modes;
348 sss_modes.push_back("\n#define USE_11_SAMPLES\n");
349 sss_modes.push_back("\n#define USE_17_SAMPLES\n");
350 sss_modes.push_back("\n#define USE_25_SAMPLES\n");
351
352 sss.shader.initialize(sss_modes);
353
354 sss.shader_version = sss.shader.version_create();
355
356 for (int i = 0; i < sss_modes.size(); i++) {
357 sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
358 }
359 }
360}
361
362SSEffects::~SSEffects() {
363 {
364 // Cleanup SS Reflections
365 ssr.shader.version_free(ssr.shader_version);
366 ssr_filter.shader.version_free(ssr_filter.shader_version);
367 ssr_scale.shader.version_free(ssr_scale.shader_version);
368
369 if (ssr.ubo.is_valid()) {
370 RD::get_singleton()->free(ssr.ubo);
371 }
372 }
373
374 {
375 // Cleanup SS downsampler
376 ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
377
378 RD::get_singleton()->free(ss_effects.mirror_sampler);
379 RD::get_singleton()->free(ss_effects.gather_constants_buffer);
380 }
381
382 {
383 // Cleanup SSIL
384 ssil.blur_shader.version_free(ssil.blur_shader_version);
385 ssil.gather_shader.version_free(ssil.gather_shader_version);
386 ssil.interleave_shader.version_free(ssil.interleave_shader_version);
387 ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
388
389 RD::get_singleton()->free(ssil.importance_map_load_counter);
390 RD::get_singleton()->free(ssil.projection_uniform_buffer);
391 }
392
393 {
394 // Cleanup SSAO
395 ssao.blur_shader.version_free(ssao.blur_shader_version);
396 ssao.gather_shader.version_free(ssao.gather_shader_version);
397 ssao.interleave_shader.version_free(ssao.interleave_shader_version);
398 ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
399
400 RD::get_singleton()->free(ssao.importance_map_load_counter);
401 }
402
403 {
404 // Cleanup Subsurface scattering
405 sss.shader.version_free(sss.shader_version);
406 }
407
408 singleton = nullptr;
409}
410
411/* SS Downsampler */
412
413void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection) {
414 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
415 ERR_FAIL_NULL(uniform_set_cache);
416 MaterialStorage *material_storage = MaterialStorage::get_singleton();
417 ERR_FAIL_NULL(material_storage);
418
419 uint32_t view_count = p_render_buffers->get_view_count();
420 Size2i full_screen_size = p_render_buffers->get_internal_size();
421 Size2i size((full_screen_size.x + 1) / 2, (full_screen_size.y + 1) / 2);
422
423 // Make sure our buffers exist, buffers are automatically cleared if view count or size changes.
424 if (!p_render_buffers->has_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH)) {
425 p_render_buffers->create_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, RD::DATA_FORMAT_R16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, size, view_count * 4, 5);
426 }
427
428 // Downsample and deinterleave the depth buffer for SSAO and SSIL
429 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
430
431 int downsample_mode = SS_EFFECTS_DOWNSAMPLE;
432 bool use_mips = ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
433
434 if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
435 downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;
436 } else if (use_mips) {
437 downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
438 }
439
440 bool use_half_size = false;
441 bool use_full_mips = false;
442
443 if (ssao_half_size && ssil_half_size) {
444 downsample_mode++;
445 use_half_size = true;
446 } else if (ssao_half_size != ssil_half_size) {
447 if (use_mips) {
448 downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
449 use_full_mips = true;
450 } else {
451 // Only need the first two mipmaps, but the cost to generate the next two is trivial
452 // TODO investigate the benefit of a shader version to generate only 2 mips
453 downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
454 use_mips = true;
455 }
456 }
457
458 RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);
459 int depth_index = use_half_size ? 1 : 0;
460
461 RD::get_singleton()->draw_command_begin_label("Downsample Depth");
462
463 RID downsample_uniform_set;
464 if (use_mips) {
465 // Grab our downsample uniform set from cache, these are automatically cleaned up if the depth textures are cleared.
466 // This also ensures we can switch between left eye and right eye uniform sets without recreating the uniform twice a frame.
467 Vector<RD::Uniform> u_depths;
468
469 // Note, use_full_mips is true if either SSAO or SSIL uses half size, but the other full size and we're using mips.
470 // That means we're filling all 5 levels.
471 // In this scenario `depth_index` will be 0.
472 for (int i = 0; i < (use_full_mips ? 4 : 3); i++) {
473 RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index + i + 1, 4, 1);
474
475 RD::Uniform u_depth;
476 u_depth.uniform_type = RD::UNIFORM_TYPE_IMAGE;
477 u_depth.binding = i;
478 u_depth.append_id(depth_mipmap);
479 u_depths.push_back(u_depth);
480 }
481
482 // This before only used SS_EFFECTS_DOWNSAMPLE_MIPMAP or SS_EFFECTS_DOWNSAMPLE_FULL_MIPS
483 downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);
484 }
485
486 float depth_linearize_mul = -p_projection.columns[3][2] * 0.5;
487 float depth_linearize_add = p_projection.columns[2][2];
488 if (depth_linearize_mul * depth_linearize_add < 0) {
489 depth_linearize_add = -depth_linearize_add;
490 }
491
492 ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
493 ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
494 ss_effects.downsample_push_constant.z_far = depth_linearize_add;
495 if (ss_effects.downsample_push_constant.orthogonal) {
496 ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
497 ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
498 }
499 ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / full_screen_size.x;
500 ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / full_screen_size.y;
501 ss_effects.downsample_push_constant.radius_sq = 1.0;
502
503 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
504
505 RID depth_texture = p_render_buffers->get_depth_texture(p_view);
506 RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index, 4, 1);
507
508 RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_texture }));
509 RD::Uniform u_depth_mipmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_mipmap }));
510
511 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]);
512 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);
513 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmap), 1);
514 if (use_mips) {
515 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, downsample_uniform_set, 2);
516 }
517 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
518
519 if (use_half_size) {
520 size.x = MAX(1, size.x >> 1);
521 size.y = MAX(1, size.y >> 1);
522 }
523
524 RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
525 RD::get_singleton()->compute_list_add_barrier(compute_list);
526 RD::get_singleton()->draw_command_end_label();
527
528 RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
529
530 ss_effects.used_full_mips_last_frame = use_full_mips;
531 ss_effects.used_half_size_last_frame = use_half_size;
532 ss_effects.used_mips_last_frame = use_mips;
533}
534
535/* SSIL */
536
537void SSEffects::ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
538 ssil_quality = p_quality;
539 ssil_half_size = p_half_size;
540 ssil_adaptive_target = p_adaptive_target;
541 ssil_blur_passes = p_blur_passes;
542 ssil_fadeout_from = p_fadeout_from;
543 ssil_fadeout_to = p_fadeout_to;
544}
545
546void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const RID *p_ssil_slices, const RID *p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
547 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
548 ERR_FAIL_NULL(uniform_set_cache);
549
550 RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
551 if ((ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
552 RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
553 }
554 RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
555
556 RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
557
558 for (int i = 0; i < 4; i++) {
559 if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
560 continue;
561 }
562
563 RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] }));
564 RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] }));
565
566 ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
567 ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
568 ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
569 ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
570 ssil.gather_push_constant.pass = i;
571 RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2);
572 RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
573
574 Size2i size;
575 // Calculate size same way as we created the buffer
576 if (ssil_half_size) {
577 size.x = (p_settings.full_screen_size.x + 3) / 4;
578 size.y = (p_settings.full_screen_size.y + 3) / 4;
579 } else {
580 size.x = (p_settings.full_screen_size.x + 1) / 2;
581 size.y = (p_settings.full_screen_size.y + 1) / 2;
582 }
583
584 RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
585 }
586 RD::get_singleton()->compute_list_add_barrier(p_compute_list);
587}
588
589void SSEffects::ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings) {
590 if (p_ssil_buffers.half_size != ssil_half_size) {
591 p_render_buffers->clear_context(RB_SCOPE_SSIL);
592 }
593
594 p_ssil_buffers.half_size = ssil_half_size;
595 if (p_ssil_buffers.half_size) {
596 p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
597 p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
598 p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
599 p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
600 } else {
601 p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
602 p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
603 p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
604 p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
605 }
606
607 uint32_t view_count = p_render_buffers->get_view_count();
608 Size2i full_size = Size2i(p_ssil_buffers.buffer_width, p_ssil_buffers.buffer_height);
609 Size2i half_size = Size2i(p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height);
610
611 // We create our intermediate and final results as render buffers.
612 // These are automatically cached and cleaned up when our viewport resizes
613 // or when our viewport gets destroyed.
614
615 if (!p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_FINAL)) { // We don't strictly have to check if it exists but we only want to clear it when we create it...
616 RID final = p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_FINAL, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT);
617 RD::get_singleton()->texture_clear(final, Color(0, 0, 0, 0), 0, 1, 0, view_count);
618 }
619
620 if (!p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_LAST_FRAME)) {
621 RID last_frame = p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_LAST_FRAME, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT, RD::TEXTURE_SAMPLES_1, p_settings.full_screen_size, 0, 6);
622 RD::get_singleton()->texture_clear(last_frame, Color(0, 0, 0, 0), 0, 6, 0, view_count);
623 }
624
625 // As we're not clearing these, and render buffers will return the cached texture if it already exists,
626 // we don't first check has_texture here
627
628 p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_DEINTERLEAVED, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
629 p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
630 p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_EDGES, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
631 p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
632 p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
633}
634
635void SSEffects::screen_space_indirect_lighting(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) {
636 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
637 ERR_FAIL_NULL(uniform_set_cache);
638 MaterialStorage *material_storage = MaterialStorage::get_singleton();
639 ERR_FAIL_NULL(material_storage);
640
641 RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
642
643 // Obtain our (cached) buffer slices for the view we are rendering.
644 RID last_frame = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, p_view, 0, 1, 6);
645 RID deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);
646 RID deinterleaved_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, 4 * p_view, 0, 4, 1);
647 RID edges = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, 4 * p_view, 0, 4, 1);
648 RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, p_view, 0);
649 RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, p_view, 0);
650
651 RID deinterleaved_slices[4];
652 RID deinterleaved_pong_slices[4];
653 RID edges_slices[4];
654 for (uint32_t i = 0; i < 4; i++) {
655 deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4 + i, 0);
656 deinterleaved_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);
657 edges_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, p_view * 4 + i, 0);
658 }
659
660 //Store projection info before starting the compute list
661 SSILProjectionUniforms projection_uniforms;
662 store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
663
664 RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
665
666 memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
667
668 RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER);
669 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
670 RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
671
672 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
673 {
674 RD::get_singleton()->draw_command_begin_label("Gather Samples");
675 ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
676 ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
677
678 ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
679 ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
680 if (ssil_half_size) {
681 ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
682 ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
683 }
684 ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75;
685 ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75;
686 float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
687 float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
688 ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
689 ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
690 ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
691 ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
692 ssil.gather_push_constant.z_near = p_projection.get_z_near();
693 ssil.gather_push_constant.z_far = p_projection.get_z_far();
694 ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
695
696 ssil.gather_push_constant.radius = p_settings.radius;
697 float radius_near_limit = (p_settings.radius * 1.2f);
698 if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {
699 radius_near_limit *= 1.50f;
700
701 if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
702 ssil.gather_push_constant.radius *= 0.8f;
703 }
704 }
705 radius_near_limit /= tan_half_fov_y;
706 ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
707 ssil.gather_push_constant.fade_out_mul = -1.0 / (ssil_fadeout_to - ssil_fadeout_from);
708 ssil.gather_push_constant.fade_out_add = ssil_fadeout_from / (ssil_fadeout_to - ssil_fadeout_from) + 1.0;
709 ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
710 ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
711 ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
712
713 ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);
714 ssil.gather_push_constant.adaptive_sample_limit = ssil_adaptive_target;
715
716 ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1);
717 ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1;
718
719 // We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.
720 // It also ensures that we're reusing the right cached entry in a multiview situation without us having to
721 // remember each instance of the uniform set.
722
723 RID projection_uniform_set;
724 {
725 RD::Uniform u_last_frame;
726 u_last_frame.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
727 u_last_frame.binding = 0;
728 u_last_frame.append_id(default_mipmap_sampler);
729 u_last_frame.append_id(last_frame);
730
731 RD::Uniform u_projection;
732 u_projection.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
733 u_projection.binding = 1;
734 u_projection.append_id(ssil.projection_uniform_buffer);
735
736 projection_uniform_set = uniform_set_cache->get_cache(shader, 3, u_last_frame, u_projection);
737 }
738
739 RID gather_uniform_set;
740 {
741 RID depth_texture_view = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, ssil_half_size ? 1 : 0, 4, 4);
742
743 RD::Uniform u_depth_texture_view;
744 u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
745 u_depth_texture_view.binding = 0;
746 u_depth_texture_view.append_id(ss_effects.mirror_sampler);
747 u_depth_texture_view.append_id(depth_texture_view);
748
749 RD::Uniform u_normal_buffer;
750 u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;
751 u_normal_buffer.binding = 1;
752 u_normal_buffer.append_id(p_normal_buffer);
753
754 RD::Uniform u_gather_constants_buffer;
755 u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
756 u_gather_constants_buffer.binding = 2;
757 u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);
758
759 gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);
760 }
761
762 RID importance_map_uniform_set;
763 {
764 RD::Uniform u_pong;
765 u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;
766 u_pong.binding = 0;
767 u_pong.append_id(deinterleaved_pong);
768
769 RD::Uniform u_importance_map;
770 u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
771 u_importance_map.binding = 1;
772 u_importance_map.append_id(default_sampler);
773 u_importance_map.append_id(importance_map);
774
775 RD::Uniform u_load_counter;
776 u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
777 u_load_counter.binding = 2;
778 u_load_counter.append_id(ssil.importance_map_load_counter);
779
780 RID shader_adaptive = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER_ADAPTIVE);
781 importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);
782 }
783
784 if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) {
785 RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
786 ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
787 ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
788 ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
789
790 //base pass
791 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
792 gather_ssil(compute_list, deinterleaved_pong_slices, edges_slices, p_settings, true, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
793
794 //generate importance map
795 RID gen_imp_shader = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 0);
796 RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));
797 RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));
798
799 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
800 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ssil_pong_with_sampler), 0);
801 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);
802 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
803 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
804 RD::get_singleton()->compute_list_add_barrier(compute_list);
805
806 // process Importance Map A
807 RID proc_imp_shader_a = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 1);
808 RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
809 RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));
810
811 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
812 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0);
813 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);
814 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
815 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
816 RD::get_singleton()->compute_list_add_barrier(compute_list);
817
818 // process Importance Map B
819 RID proc_imp_shader_b = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2);
820 RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
821
822 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
823 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0);
824 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);
825 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
826 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
827 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
828 RD::get_singleton()->compute_list_add_barrier(compute_list);
829
830 RD::get_singleton()->draw_command_end_label(); // Importance Map
831
832 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
833 } else {
834 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
835 }
836
837 gather_ssil(compute_list, deinterleaved_slices, edges_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
838 RD::get_singleton()->draw_command_end_label(); //Gather
839 }
840
841 {
842 RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
843 ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
844 ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
845 ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
846
847 int blur_passes = ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? ssil_blur_passes : 1;
848
849 shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);
850
851 for (int pass = 0; pass < blur_passes; pass++) {
852 int blur_pipeline = SSIL_BLUR_PASS;
853 if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
854 blur_pipeline = SSIL_BLUR_PASS_SMART;
855 if (pass < blur_passes - 2) {
856 blur_pipeline = SSIL_BLUR_PASS_WIDE;
857 }
858 }
859
860 RID blur_shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, blur_pipeline - SSIL_BLUR_PASS);
861
862 for (int i = 0; i < 4; i++) {
863 if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
864 continue;
865 }
866
867 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
868 if (pass % 2 == 0) {
869 if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
870 RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_slices[i] }));
871 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);
872 } else {
873 RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_slices[i] }));
874 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);
875 }
876
877 RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_pong_slices[i] }));
878 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_pong_slice), 1);
879 } else {
880 if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
881 RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong_slices[i] }));
882 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);
883 } else {
884 RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_pong_slices[i] }));
885 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);
886 }
887
888 RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_slices[i] }));
889 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_slice), 1);
890 }
891
892 RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges_slices[i] }));
893 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 2, u_edges_slice), 2);
894
895 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
896
897 // Use the size of the actual buffer we're processing here or we won't cover the entire image.
898 int x_groups = p_ssil_buffers.buffer_width;
899 int y_groups = p_ssil_buffers.buffer_height;
900
901 RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
902 if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
903 RD::get_singleton()->compute_list_add_barrier(compute_list);
904 }
905 }
906 }
907
908 RD::get_singleton()->draw_command_end_label(); // Blur
909 }
910
911 {
912 RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
913 ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
914 ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
915 ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
916 ssil.interleave_push_constant.size_modifier = uint32_t(ssil_half_size ? 4 : 2);
917
918 int interleave_pipeline = SSIL_INTERLEAVE_HALF;
919 if (ssil_quality == RS::ENV_SSIL_QUALITY_LOW) {
920 interleave_pipeline = SSIL_INTERLEAVE;
921 } else if (ssil_quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
922 interleave_pipeline = SSIL_INTERLEAVE_SMART;
923 }
924
925 shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);
926
927 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
928
929 RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, p_view, 0);
930 RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ final }));
931 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);
932
933 if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) {
934 RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved }));
935 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);
936 } else {
937 RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));
938 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);
939 }
940
941 RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges }));
942 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);
943
944 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
945
946 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
947 RD::get_singleton()->compute_list_add_barrier(compute_list);
948 RD::get_singleton()->draw_command_end_label(); // Interleave
949 }
950
951 RD::get_singleton()->draw_command_end_label(); // SSIL
952
953 RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
954
955 int zero[1] = { 0 };
956 RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
957}
958
959/* SSAO */
960
961void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
962 ssao_quality = p_quality;
963 ssao_half_size = p_half_size;
964 ssao_adaptive_target = p_adaptive_target;
965 ssao_blur_passes = p_blur_passes;
966 ssao_fadeout_from = p_fadeout_from;
967 ssao_fadeout_to = p_fadeout_to;
968}
969
970void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const RID *p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
971 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
972 ERR_FAIL_NULL(uniform_set_cache);
973
974 RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
975 if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
976 RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
977 }
978
979 RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //
980
981 for (int i = 0; i < 4; i++) {
982 if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
983 continue;
984 }
985
986 RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ao_slices[i] }));
987
988 ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
989 ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
990 ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
991 ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
992 ssao.gather_push_constant.pass = i;
993 RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);
994 RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
995
996 Size2i size;
997 // Make sure we use the same size as with which our buffer was created
998 if (ssao_half_size) {
999 size.x = (p_settings.full_screen_size.x + 3) / 4;
1000 size.y = (p_settings.full_screen_size.y + 3) / 4;
1001 } else {
1002 size.x = (p_settings.full_screen_size.x + 1) / 2;
1003 size.y = (p_settings.full_screen_size.y + 1) / 2;
1004 }
1005
1006 RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
1007 }
1008 RD::get_singleton()->compute_list_add_barrier(p_compute_list);
1009}
1010
1011void SSEffects::ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings) {
1012 if (p_ssao_buffers.half_size != ssao_half_size) {
1013 p_render_buffers->clear_context(RB_SCOPE_SSAO);
1014 }
1015
1016 p_ssao_buffers.half_size = ssao_half_size;
1017 if (ssao_half_size) {
1018 p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
1019 p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
1020 p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
1021 p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
1022 } else {
1023 p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
1024 p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
1025 p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
1026 p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
1027 }
1028
1029 uint32_t view_count = p_render_buffers->get_view_count();
1030 Size2i full_size = Size2i(p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height);
1031 Size2i half_size = Size2i(p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height);
1032
1033 // As we're not clearing these, and render buffers will return the cached texture if it already exists,
1034 // we don't first check has_texture here
1035
1036 p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_DEINTERLEAVED, RD::DATA_FORMAT_R8G8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
1037 p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, RD::DATA_FORMAT_R8G8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, full_size, 4 * view_count);
1038 p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
1039 p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, half_size);
1040 p_render_buffers->create_texture(RB_SCOPE_SSAO, RB_FINAL, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1);
1041}
1042
1043void SSEffects::generate_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, uint32_t p_view, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) {
1044 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1045 ERR_FAIL_NULL(uniform_set_cache);
1046 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1047 ERR_FAIL_NULL(material_storage);
1048
1049 // Obtain our (cached) buffer slices for the view we are rendering.
1050 RID ao_deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);
1051 RID ao_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4, 0, 4, 1);
1052 RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, p_view, 0);
1053 RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, p_view, 0);
1054 RID ao_final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, p_view, 0);
1055
1056 RID ao_deinterleaved_slices[4];
1057 RID ao_pong_slices[4];
1058 for (uint32_t i = 0; i < 4; i++) {
1059 ao_deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4 + i, 0);
1060 ao_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);
1061 }
1062
1063 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1064 memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
1065 /* FIRST PASS */
1066
1067 RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER);
1068 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1069
1070 RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
1071 /* SECOND PASS */
1072 // Sample SSAO
1073 {
1074 RD::get_singleton()->draw_command_begin_label("Gather Samples");
1075 ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
1076 ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
1077
1078 ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
1079 ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
1080 if (ssao_half_size) {
1081 ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
1082 ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
1083 }
1084 ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75;
1085 ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75;
1086 float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
1087 float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
1088 ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
1089 ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
1090 ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
1091 ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
1092 ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
1093
1094 ssao.gather_push_constant.radius = p_settings.radius;
1095 float radius_near_limit = (p_settings.radius * 1.2f);
1096 if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {
1097 radius_near_limit *= 1.50f;
1098
1099 if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
1100 ssao.gather_push_constant.radius *= 0.8f;
1101 }
1102 }
1103 radius_near_limit /= tan_half_fov_y;
1104 ssao.gather_push_constant.intensity = p_settings.intensity;
1105 ssao.gather_push_constant.shadow_power = p_settings.power;
1106 ssao.gather_push_constant.shadow_clamp = 0.98;
1107 ssao.gather_push_constant.fade_out_mul = -1.0 / (ssao_fadeout_to - ssao_fadeout_from);
1108 ssao.gather_push_constant.fade_out_add = ssao_fadeout_from / (ssao_fadeout_to - ssao_fadeout_from) + 1.0;
1109 ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
1110 ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
1111 ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
1112
1113 ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);
1114 ssao.gather_push_constant.adaptive_sample_limit = ssao_adaptive_target;
1115
1116 ssao.gather_push_constant.detail_intensity = p_settings.detail;
1117 ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1);
1118 ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1;
1119
1120 // We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.
1121 // It also ensures that we're reusing the right cached entry in a multiview situation without us having to
1122 // remember each instance of the uniform set.
1123 RID gather_uniform_set;
1124 {
1125 RID depth_texture_view = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, ssao_half_size ? 1 : 0, 4, 4);
1126
1127 RD::Uniform u_depth_texture_view;
1128 u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
1129 u_depth_texture_view.binding = 0;
1130 u_depth_texture_view.append_id(ss_effects.mirror_sampler);
1131 u_depth_texture_view.append_id(depth_texture_view);
1132
1133 RD::Uniform u_normal_buffer;
1134 u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;
1135 u_normal_buffer.binding = 1;
1136 u_normal_buffer.append_id(p_normal_buffer);
1137
1138 RD::Uniform u_gather_constants_buffer;
1139 u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
1140 u_gather_constants_buffer.binding = 2;
1141 u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);
1142
1143 gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);
1144 }
1145
1146 RID importance_map_uniform_set;
1147 {
1148 RD::Uniform u_pong;
1149 u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;
1150 u_pong.binding = 0;
1151 u_pong.append_id(ao_pong);
1152
1153 RD::Uniform u_importance_map;
1154 u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
1155 u_importance_map.binding = 1;
1156 u_importance_map.append_id(default_sampler);
1157 u_importance_map.append_id(importance_map);
1158
1159 RD::Uniform u_load_counter;
1160 u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
1161 u_load_counter.binding = 2;
1162 u_load_counter.append_id(ssao.importance_map_load_counter);
1163
1164 RID shader_adaptive = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER_ADAPTIVE);
1165 importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);
1166 }
1167
1168 if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) {
1169 RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
1170 ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
1171 ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
1172 ssao.importance_map_push_constant.intensity = p_settings.intensity;
1173 ssao.importance_map_push_constant.power = p_settings.power;
1174
1175 //base pass
1176 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
1177 gather_ssao(compute_list, ao_pong_slices, p_settings, true, gather_uniform_set, RID());
1178
1179 //generate importance map
1180 RID gen_imp_shader = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 0);
1181 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
1182
1183 RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));
1184 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ao_pong_with_sampler), 0);
1185
1186 RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));
1187 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);
1188
1189 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
1190 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
1191 RD::get_singleton()->compute_list_add_barrier(compute_list);
1192
1193 //process importance map A
1194 RID proc_imp_shader_a = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 1);
1195 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
1196
1197 RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
1198 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 0, u_importance_map_with_sampler), 0);
1199
1200 RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));
1201 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);
1202
1203 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
1204 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
1205 RD::get_singleton()->compute_list_add_barrier(compute_list);
1206
1207 //process Importance Map B
1208 RID proc_imp_shader_b = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2);
1209 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
1210
1211 RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
1212 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 0, u_importance_map_pong_with_sampler), 0);
1213
1214 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);
1215 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
1216 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
1217 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
1218 RD::get_singleton()->compute_list_add_barrier(compute_list);
1219
1220 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
1221 RD::get_singleton()->draw_command_end_label(); // Importance Map
1222 } else {
1223 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
1224 }
1225
1226 gather_ssao(compute_list, ao_deinterleaved_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set);
1227 RD::get_singleton()->draw_command_end_label(); // Gather SSAO
1228 }
1229
1230 // /* THIRD PASS */
1231 // // Blur
1232 //
1233 {
1234 RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
1235 ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
1236 ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
1237 ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
1238
1239 int blur_passes = ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? ssao_blur_passes : 1;
1240
1241 shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);
1242
1243 for (int pass = 0; pass < blur_passes; pass++) {
1244 int blur_pipeline = SSAO_BLUR_PASS;
1245 if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
1246 if (pass < blur_passes - 2) {
1247 blur_pipeline = SSAO_BLUR_PASS_WIDE;
1248 } else {
1249 blur_pipeline = SSAO_BLUR_PASS_SMART;
1250 }
1251 }
1252
1253 for (int i = 0; i < 4; i++) {
1254 if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
1255 continue;
1256 }
1257
1258 RID blur_shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, blur_pipeline - SSAO_BLUR_PASS);
1259 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
1260 if (pass % 2 == 0) {
1261 if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
1262 RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved_slices[i] }));
1263 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);
1264 } else {
1265 RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_deinterleaved_slices[i] }));
1266 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);
1267 }
1268
1269 RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_pong_slices[i] }));
1270 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_pong_slices), 1);
1271 } else {
1272 if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
1273 RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong_slices[i] }));
1274 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);
1275 } else {
1276 RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_pong_slices[i] }));
1277 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);
1278 }
1279
1280 RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_deinterleaved_slices[i] }));
1281 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_slices), 1);
1282 }
1283 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
1284
1285 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height, 1);
1286 }
1287
1288 if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
1289 RD::get_singleton()->compute_list_add_barrier(compute_list);
1290 }
1291 }
1292 RD::get_singleton()->draw_command_end_label(); // Blur
1293 }
1294
1295 /* FOURTH PASS */
1296 // Interleave buffers
1297 // back to full size
1298 {
1299 RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
1300 ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
1301 ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
1302 ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
1303 ssao.interleave_push_constant.size_modifier = uint32_t(ssao_half_size ? 4 : 2);
1304
1305 shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);
1306
1307 int interleave_pipeline = SSAO_INTERLEAVE_HALF;
1308 if (ssao_quality == RS::ENV_SSAO_QUALITY_LOW) {
1309 interleave_pipeline = SSAO_INTERLEAVE;
1310 } else if (ssao_quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
1311 interleave_pipeline = SSAO_INTERLEAVE_SMART;
1312 }
1313
1314 RID interleave_shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, interleave_pipeline - SSAO_INTERLEAVE);
1315 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
1316
1317 RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_final }));
1318 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 0, u_upscale_buffer), 0);
1319
1320 if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) {
1321 RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved }));
1322 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);
1323 } else {
1324 RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));
1325 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);
1326 }
1327
1328 RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
1329
1330 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
1331 RD::get_singleton()->compute_list_add_barrier(compute_list);
1332 RD::get_singleton()->draw_command_end_label(); // Interleave
1333 }
1334 RD::get_singleton()->draw_command_end_label(); //SSAO
1335 RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
1336
1337 int zero[1] = { 0 };
1338 RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
1339}
1340
1341/* Screen Space Reflection */
1342
1343void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
1344 ssr_roughness_quality = p_quality;
1345}
1346
1347void SSEffects::ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format) {
1348 if (p_ssr_buffers.roughness_quality != ssr_roughness_quality) {
1349 // Buffers will already be cleared if view count or viewport size has changed, also cleared them if we change roughness.
1350 p_render_buffers->clear_context(RB_SCOPE_SSR);
1351 }
1352
1353 Size2i internal_size = p_render_buffers->get_internal_size();
1354 p_ssr_buffers.size = Size2i(internal_size.x / 2, internal_size.y / 2);
1355 p_ssr_buffers.roughness_quality = ssr_roughness_quality;
1356
1357 // We are using barriers so we do not need to allocate textures for both views on anything but output...
1358
1359 p_render_buffers->create_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED, RD::DATA_FORMAT_R32_SFLOAT, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);
1360 p_render_buffers->create_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED, RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);
1361
1362 if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_render_buffers->has_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS)) {
1363 p_render_buffers->create_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 2); // 2 layers, for our two blur stages
1364 }
1365
1366 p_render_buffers->create_texture(RB_SCOPE_SSR, RB_INTERMEDIATE, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);
1367 p_render_buffers->create_texture(RB_SCOPE_SSR, RB_OUTPUT, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size);
1368}
1369
1370void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const Projection *p_projections, const Vector3 *p_eye_offsets) {
1371 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1372 ERR_FAIL_NULL(uniform_set_cache);
1373 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1374 ERR_FAIL_NULL(material_storage);
1375
1376 uint32_t view_count = p_render_buffers->get_view_count();
1377
1378 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1379
1380 {
1381 // Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders
1382 ScreenSpaceReflectionSceneData scene_data;
1383
1384 if (ssr.ubo.is_null()) {
1385 ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));
1386 }
1387
1388 for (uint32_t v = 0; v < view_count; v++) {
1389 store_camera(p_projections[v], scene_data.projection[v]);
1390 store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
1391 scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
1392 scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
1393 scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
1394 scene_data.eye_offset[v][3] = 0.0;
1395 }
1396
1397 RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
1398 }
1399
1400 uint32_t pipeline_specialization = 0;
1401 if (view_count > 1) {
1402 pipeline_specialization |= SSR_MULTIVIEW;
1403 }
1404
1405 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1406
1407 for (uint32_t v = 0; v < view_count; v++) {
1408 // get buffers we need to use for this view
1409 RID diffuse_slice = p_render_buffers->get_internal_texture(v);
1410 RID depth_slice = p_render_buffers->get_depth_texture(v);
1411 RID depth_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED);
1412 RID normal_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED);
1413 RID intermediate = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_INTERMEDIATE);
1414 RID output = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_OUTPUT, v, 0);
1415
1416 RID blur_radius[2];
1417 if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
1418 blur_radius[0] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 0, 0);
1419 blur_radius[1] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 1, 0);
1420 }
1421
1422 RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v));
1423
1424 { //scale color and depth to half
1425 RD::get_singleton()->draw_command_begin_label("SSR Scale");
1426
1427 ScreenSpaceReflectionScalePushConstant push_constant;
1428 push_constant.view_index = v;
1429 push_constant.camera_z_far = p_projections[v].get_z_far();
1430 push_constant.camera_z_near = p_projections[v].get_z_near();
1431 push_constant.orthogonal = p_projections[v].is_orthogonal();
1432 push_constant.filter = false; // Enabling causes artifacts.
1433 push_constant.screen_size[0] = p_ssr_buffers.size.x;
1434 push_constant.screen_size[1] = p_ssr_buffers.size.y;
1435
1436 RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0);
1437
1438 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]);
1439
1440 RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, diffuse_slice }));
1441 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0);
1442
1443 RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_slice }));
1444 RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] }));
1445 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1);
1446
1447 RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
1448 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
1449
1450 RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled }));
1451 RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ normal_scaled }));
1452 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3);
1453
1454 RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
1455 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
1456
1457 RD::get_singleton()->compute_list_add_barrier(compute_list);
1458
1459 RD::get_singleton()->draw_command_end_label();
1460 }
1461
1462 {
1463 RD::get_singleton()->draw_command_begin_label("SSR main");
1464
1465 ScreenSpaceReflectionPushConstant push_constant;
1466 push_constant.view_index = v;
1467 push_constant.camera_z_far = p_projections[v].get_z_far();
1468 push_constant.camera_z_near = p_projections[v].get_z_near();
1469 push_constant.orthogonal = p_projections[v].is_orthogonal();
1470 push_constant.screen_size[0] = p_ssr_buffers.size.x;
1471 push_constant.screen_size[1] = p_ssr_buffers.size.y;
1472 push_constant.curve_fade_in = p_fade_in;
1473 push_constant.distance_fade = p_fade_out;
1474 push_constant.num_steps = p_max_steps;
1475 push_constant.depth_tolerance = p_tolerance;
1476 push_constant.use_half_res = true;
1477 push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]);
1478 push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]);
1479 push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
1480 push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
1481
1482 ScreenSpaceReflectionMode mode = (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;
1483 RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode);
1484
1485 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]);
1486
1487 RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
1488 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
1489
1490 // read from intermediate
1491 RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
1492 RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ depth_scaled }));
1493 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0);
1494
1495 if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
1496 // write to output and blur radius
1497 RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));
1498 RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] }));
1499 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output, u_blur_radius), 1);
1500 } else {
1501 // We are only writing output
1502 RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));
1503 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output), 1);
1504 }
1505
1506 RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled }));
1507 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2);
1508
1509 RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] }));
1510 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3);
1511
1512 RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant));
1513 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
1514
1515 RD::get_singleton()->draw_command_end_label();
1516 }
1517
1518 if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
1519 RD::get_singleton()->draw_command_begin_label("SSR filter");
1520 //blur
1521
1522 RD::get_singleton()->compute_list_add_barrier(compute_list);
1523
1524 ScreenSpaceReflectionFilterPushConstant push_constant;
1525 push_constant.view_index = v;
1526 push_constant.orthogonal = p_projections[v].is_orthogonal();
1527 push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));
1528 push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]);
1529 push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]);
1530 push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
1531 push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
1532 push_constant.vertical = 0;
1533 if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
1534 push_constant.steps = p_max_steps / 3;
1535 push_constant.increment = 3;
1536 } else if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
1537 push_constant.steps = p_max_steps / 2;
1538 push_constant.increment = 2;
1539 } else {
1540 push_constant.steps = p_max_steps;
1541 push_constant.increment = 1;
1542 }
1543
1544 push_constant.screen_size[0] = p_ssr_buffers.size.width;
1545 push_constant.screen_size[1] = p_ssr_buffers.size.height;
1546
1547 // Horizontal pass
1548
1549 SSRReflectionMode mode = SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL;
1550
1551 RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
1552
1553 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
1554
1555 RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));
1556 RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] }));
1557 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_blur_radius), 0);
1558
1559 RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled }));
1560 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
1561
1562 RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
1563 RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[1] }));
1564 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate, u_blur_radius2), 2);
1565
1566 RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled }));
1567 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
1568
1569 RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
1570 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
1571
1572 RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
1573 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
1574 RD::get_singleton()->compute_list_add_barrier(compute_list);
1575
1576 // Vertical pass
1577
1578 mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL;
1579 shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
1580
1581 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
1582
1583 push_constant.vertical = 1;
1584
1585 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius2), 0);
1586 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
1587 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2);
1588 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
1589 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
1590
1591 RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
1592 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
1593
1594 if (v != view_count - 1) {
1595 RD::get_singleton()->compute_list_add_barrier(compute_list);
1596 }
1597
1598 RD::get_singleton()->draw_command_end_label();
1599 }
1600
1601 RD::get_singleton()->draw_command_end_label();
1602 }
1603
1604 RD::get_singleton()->compute_list_end();
1605}
1606
1607/* Subsurface scattering */
1608
1609void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
1610 sss_quality = p_quality;
1611}
1612
1613RS::SubSurfaceScatteringQuality SSEffects::sss_get_quality() const {
1614 return sss_quality;
1615}
1616
1617void SSEffects::sss_set_scale(float p_scale, float p_depth_scale) {
1618 sss_scale = p_scale;
1619 sss_depth_scale = p_depth_scale;
1620}
1621
1622void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size) {
1623 UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1624 ERR_FAIL_NULL(uniform_set_cache);
1625 MaterialStorage *material_storage = MaterialStorage::get_singleton();
1626 ERR_FAIL_NULL(material_storage);
1627
1628 RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1629
1630 // Our intermediate buffer is only created if we haven't created it already.
1631 RD::DataFormat format = p_render_buffers->get_base_data_format();
1632 uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
1633 uint32_t layers = 1; // We only need one layer, we're handling one view at a time
1634 uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);
1635 RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);
1636
1637 Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
1638 p.normal /= p.d;
1639 float unit_size = p.normal.x;
1640
1641 { //scale color and depth to half
1642 RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1643
1644 sss.push_constant.camera_z_far = p_camera.get_z_far();
1645 sss.push_constant.camera_z_near = p_camera.get_z_near();
1646 sss.push_constant.orthogonal = p_camera.is_orthogonal();
1647 sss.push_constant.unit_size = unit_size;
1648 sss.push_constant.screen_size[0] = p_screen_size.x;
1649 sss.push_constant.screen_size[1] = p_screen_size.y;
1650 sss.push_constant.vertical = false;
1651 sss.push_constant.scale = sss_scale;
1652 sss.push_constant.depth_scale = sss_depth_scale;
1653
1654 RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1);
1655 RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1]);
1656
1657 RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
1658 RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
1659 RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));
1660 RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
1661 RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));
1662
1663 // horizontal
1664
1665 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);
1666 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
1667 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
1668
1669 RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
1670
1671 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
1672
1673 RD::get_singleton()->compute_list_add_barrier(compute_list);
1674
1675 // vertical
1676
1677 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);
1678 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);
1679 RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
1680
1681 sss.push_constant.vertical = true;
1682 RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
1683
1684 RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
1685
1686 RD::get_singleton()->compute_list_end();
1687 }
1688}
1689