Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/rendering/renderer_rd/effects/ss_effects.cpp
20912 views
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/effects/copy_effects.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
39
using namespace RendererRD;
40
41
SSEffects *SSEffects::singleton = nullptr;
42
43
static _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
51
SSEffects::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].create_compute_pipeline(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].create_compute_pipeline(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].create_compute_pipeline(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].create_compute_pipeline(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].create_compute_pipeline(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].create_compute_pipeline(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].create_compute_pipeline(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].create_compute_pipeline(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].create_compute_pipeline(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
271
pipeline++;
272
}
273
}
274
275
ERR_FAIL_COND(pipeline != SSAO_MAX);
276
277
ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
278
}
279
280
// Screen Space Reflections
281
ssr_half_size = GLOBAL_GET("rendering/environment/screen_space_reflection/half_size");
282
283
{
284
{
285
Vector<String> ssr_downsample_modes;
286
ssr_downsample_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_DEFAULT
287
ssr_downsample_modes.push_back("\n#define MODE_ODD_WIDTH\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH
288
ssr_downsample_modes.push_back("\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_HEIGHT
289
ssr_downsample_modes.push_back("\n#define MODE_ODD_WIDTH\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH_AND_HEIGHT
290
291
ssr.downsample_shader.initialize(ssr_downsample_modes);
292
ssr.downsample_shader_version = ssr.downsample_shader.version_create();
293
294
for (uint32_t i = 0; i < SCREEN_SPACE_REFLECTION_DOWNSAMPLE_MAX; i++) {
295
ssr.downsample_pipelines[i].create_compute_pipeline(ssr.downsample_shader.version_get_shader(ssr.downsample_shader_version, i));
296
}
297
}
298
299
{
300
Vector<String> ssr_hiz_modes;
301
ssr_hiz_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_HIZ_DEFAULT
302
ssr_hiz_modes.push_back("\n#define MODE_ODD_WIDTH\n"); // SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH
303
ssr_hiz_modes.push_back("\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_HIZ_ODD_HEIGHT
304
ssr_hiz_modes.push_back("\n#define MODE_ODD_WIDTH\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH_AND_HEIGHT
305
306
ssr.hiz_shader.initialize(ssr_hiz_modes);
307
ssr.hiz_shader_version = ssr.hiz_shader.version_create();
308
309
for (uint32_t i = 0; i < SCREEN_SPACE_REFLECTION_HIZ_MAX; i++) {
310
ssr.hiz_pipelines[i].create_compute_pipeline(ssr.hiz_shader.version_get_shader(ssr.hiz_shader_version, i));
311
}
312
}
313
314
{
315
Vector<String> ssr_modes;
316
ssr_modes.push_back("\n");
317
318
ssr.ssr_shader.initialize(ssr_modes);
319
ssr.ssr_shader_version = ssr.ssr_shader.version_create();
320
321
ssr.ssr_pipeline.create_compute_pipeline(ssr.ssr_shader.version_get_shader(ssr.ssr_shader_version, 0));
322
}
323
324
{
325
Vector<String> ssr_filter_modes;
326
ssr_filter_modes.push_back("\n");
327
328
ssr.filter_shader.initialize(ssr_filter_modes);
329
ssr.filter_shader_version = ssr.filter_shader.version_create();
330
331
ssr.filter_pipeline.create_compute_pipeline(ssr.filter_shader.version_get_shader(ssr.filter_shader_version, 0));
332
}
333
334
{
335
Vector<String> ssr_resolve_modes;
336
ssr_resolve_modes.push_back("\n");
337
338
ssr.resolve_shader.initialize(ssr_resolve_modes);
339
ssr.resolve_shader_version = ssr.resolve_shader.version_create();
340
341
ssr.resolve_pipeline.create_compute_pipeline(ssr.resolve_shader.version_get_shader(ssr.resolve_shader_version, 0));
342
}
343
}
344
345
// Subsurface scattering
346
sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
347
sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
348
sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
349
350
{
351
Vector<String> sss_modes;
352
sss_modes.push_back("\n#define USE_11_SAMPLES\n");
353
sss_modes.push_back("\n#define USE_17_SAMPLES\n");
354
sss_modes.push_back("\n#define USE_25_SAMPLES\n");
355
356
sss.shader.initialize(sss_modes);
357
358
sss.shader_version = sss.shader.version_create();
359
360
for (int i = 0; i < SUBSURFACE_SCATTERING_MODE_MAX; i++) {
361
sss.pipelines[i].create_compute_pipeline(sss.shader.version_get_shader(sss.shader_version, i));
362
}
363
}
364
}
365
366
void SSEffects::allocate_last_frame_buffer(Ref<RenderSceneBuffersRD> p_render_buffers, bool p_use_ssil, bool p_use_ssr) {
367
Size2i last_frame_size = p_render_buffers->get_internal_size();
368
uint32_t mipmaps = 1;
369
uint32_t view_count = p_render_buffers->get_view_count();
370
371
if (!p_use_ssil && p_use_ssr && ssr_half_size) {
372
last_frame_size /= 2;
373
}
374
375
if (p_use_ssil) {
376
mipmaps = 6;
377
}
378
379
bool should_create = true;
380
bool has_texture = p_render_buffers->has_texture(RB_SCOPE_SSLF, RB_LAST_FRAME);
381
382
if (has_texture) {
383
RID last_frame_texture = p_render_buffers->get_texture(RB_SCOPE_SSLF, RB_LAST_FRAME);
384
RD::TextureFormat texture_format = RD::get_singleton()->texture_get_format(last_frame_texture);
385
should_create = texture_format.width != (uint32_t)last_frame_size.width || texture_format.height != (uint32_t)last_frame_size.height || texture_format.mipmaps != mipmaps || texture_format.array_layers != view_count;
386
}
387
388
if (should_create) {
389
if (has_texture) {
390
p_render_buffers->clear_context(RB_SCOPE_SSLF);
391
}
392
393
RID last_frame_texture = p_render_buffers->create_texture(RB_SCOPE_SSLF, 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, last_frame_size, view_count, mipmaps);
394
RD::get_singleton()->texture_clear(last_frame_texture, Color(0, 0, 0, 0), 0, mipmaps, 0, view_count);
395
}
396
}
397
398
void SSEffects::copy_internal_texture_to_last_frame(Ref<RenderSceneBuffersRD> p_render_buffers, CopyEffects &p_copy_effects) {
399
uint32_t mipmaps = p_render_buffers->get_texture_format(RB_SCOPE_SSLF, RB_LAST_FRAME).mipmaps;
400
for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
401
for (uint32_t m = 0; m < mipmaps; m++) {
402
RID source;
403
if (m == 0) {
404
source = p_render_buffers->get_internal_texture(v);
405
} else {
406
source = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, m - 1);
407
}
408
409
RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, m);
410
411
Size2i source_size = RD::get_singleton()->texture_size(source);
412
Size2i dest_size = RD::get_singleton()->texture_size(dest);
413
414
if (m == 0 && source_size == dest_size) {
415
p_copy_effects.copy_to_rect(source, dest, Rect2i(Vector2i(), source_size), false, false, false, false, false, true);
416
} else {
417
p_copy_effects.make_mipmap(source, dest, dest_size);
418
}
419
}
420
}
421
}
422
423
SSEffects::~SSEffects() {
424
{
425
// Cleanup SS Reflections
426
for (int i = 0; i < SCREEN_SPACE_REFLECTION_DOWNSAMPLE_MAX; i++) {
427
ssr.downsample_pipelines[i].free();
428
}
429
for (int i = 0; i < SCREEN_SPACE_REFLECTION_HIZ_MAX; i++) {
430
ssr.hiz_pipelines[i].free();
431
}
432
ssr.ssr_pipeline.free();
433
ssr.filter_pipeline.free();
434
ssr.resolve_pipeline.free();
435
436
ssr.downsample_shader.version_free(ssr.downsample_shader_version);
437
ssr.hiz_shader.version_free(ssr.hiz_shader_version);
438
ssr.ssr_shader.version_free(ssr.ssr_shader_version);
439
ssr.filter_shader.version_free(ssr.filter_shader_version);
440
ssr.resolve_shader.version_free(ssr.resolve_shader_version);
441
442
if (ssr.ubo.is_valid()) {
443
RD::get_singleton()->free_rid(ssr.ubo);
444
}
445
}
446
447
{
448
// Cleanup SS downsampler
449
for (int i = 0; i < SS_EFFECTS_MAX; i++) {
450
ss_effects.pipelines[i].free();
451
}
452
453
ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
454
455
RD::get_singleton()->free_rid(ss_effects.mirror_sampler);
456
RD::get_singleton()->free_rid(ss_effects.gather_constants_buffer);
457
}
458
459
{
460
// Cleanup SSIL
461
for (int i = 0; i < SSIL_MAX; i++) {
462
ssil.pipelines[i].free();
463
}
464
465
ssil.blur_shader.version_free(ssil.blur_shader_version);
466
ssil.gather_shader.version_free(ssil.gather_shader_version);
467
ssil.interleave_shader.version_free(ssil.interleave_shader_version);
468
ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
469
470
RD::get_singleton()->free_rid(ssil.importance_map_load_counter);
471
RD::get_singleton()->free_rid(ssil.projection_uniform_buffer);
472
}
473
474
{
475
// Cleanup SSAO
476
for (int i = 0; i < SSAO_MAX; i++) {
477
ssao.pipelines[i].free();
478
}
479
480
ssao.blur_shader.version_free(ssao.blur_shader_version);
481
ssao.gather_shader.version_free(ssao.gather_shader_version);
482
ssao.interleave_shader.version_free(ssao.interleave_shader_version);
483
ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
484
485
RD::get_singleton()->free_rid(ssao.importance_map_load_counter);
486
}
487
488
{
489
// Cleanup Subsurface scattering
490
for (int i = 0; i < SUBSURFACE_SCATTERING_MODE_MAX; i++) {
491
sss.pipelines[i].free();
492
}
493
494
sss.shader.version_free(sss.shader_version);
495
}
496
497
singleton = nullptr;
498
}
499
500
/* SS Downsampler */
501
502
void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection) {
503
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
504
ERR_FAIL_NULL(uniform_set_cache);
505
MaterialStorage *material_storage = MaterialStorage::get_singleton();
506
ERR_FAIL_NULL(material_storage);
507
508
uint32_t view_count = p_render_buffers->get_view_count();
509
Size2i full_screen_size = p_render_buffers->get_internal_size();
510
Size2i size((full_screen_size.x + 1) / 2, (full_screen_size.y + 1) / 2);
511
512
// Make sure our buffers exist, buffers are automatically cleared if view count or size changes.
513
if (!p_render_buffers->has_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH)) {
514
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);
515
}
516
517
// Downsample and deinterleave the depth buffer for SSAO and SSIL
518
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
519
520
int downsample_mode = SS_EFFECTS_DOWNSAMPLE;
521
bool use_mips = ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
522
523
if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
524
downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;
525
} else if (use_mips) {
526
downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
527
}
528
529
bool use_half_size = false;
530
bool use_full_mips = false;
531
532
if (ssao_half_size && ssil_half_size) {
533
downsample_mode++;
534
use_half_size = true;
535
} else if (ssao_half_size != ssil_half_size) {
536
if (use_mips) {
537
downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
538
use_full_mips = true;
539
} else {
540
// Only need the first two mipmaps, but the cost to generate the next two is trivial
541
// TODO investigate the benefit of a shader version to generate only 2 mips
542
downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
543
use_mips = true;
544
}
545
}
546
547
RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);
548
int depth_index = use_half_size ? 1 : 0;
549
550
RD::get_singleton()->draw_command_begin_label("Downsample Depth");
551
552
RID downsample_uniform_set;
553
if (use_mips) {
554
// Grab our downsample uniform set from cache, these are automatically cleaned up if the depth textures are cleared.
555
// This also ensures we can switch between left eye and right eye uniform sets without recreating the uniform twice a frame.
556
thread_local LocalVector<RD::Uniform> u_depths;
557
u_depths.clear();
558
559
// Note, use_full_mips is true if either SSAO or SSIL uses half size, but the other full size and we're using mips.
560
// That means we're filling all 5 levels.
561
// In this scenario `depth_index` will be 0.
562
for (int i = 0; i < (use_full_mips ? 4 : 3); i++) {
563
RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index + i + 1, 4, 1);
564
565
RD::Uniform u_depth;
566
u_depth.uniform_type = RD::UNIFORM_TYPE_IMAGE;
567
u_depth.binding = i;
568
u_depth.append_id(depth_mipmap);
569
u_depths.push_back(u_depth);
570
}
571
572
// This before only used SS_EFFECTS_DOWNSAMPLE_MIPMAP or SS_EFFECTS_DOWNSAMPLE_FULL_MIPS
573
downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);
574
}
575
576
Projection correction;
577
correction.set_depth_correction(false);
578
Projection temp = correction * p_projection;
579
580
float depth_linearize_mul = -temp.columns[3][2];
581
float depth_linearize_add = temp.columns[2][2];
582
if (depth_linearize_mul * depth_linearize_add < 0) {
583
depth_linearize_add = -depth_linearize_add;
584
}
585
586
ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
587
ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
588
ss_effects.downsample_push_constant.z_far = depth_linearize_add;
589
if (ss_effects.downsample_push_constant.orthogonal) {
590
ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
591
ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
592
}
593
ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / full_screen_size.x;
594
ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / full_screen_size.y;
595
ss_effects.downsample_push_constant.radius_sq = 1.0;
596
597
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
598
599
RID depth_texture = p_render_buffers->get_depth_texture(p_view);
600
RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index, 4, 1);
601
602
RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_texture }));
603
RD::Uniform u_depth_mipmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_mipmap }));
604
605
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode].get_rid());
606
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);
607
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmap), 1);
608
if (use_mips) {
609
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, downsample_uniform_set, 2);
610
}
611
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
612
613
if (use_half_size) {
614
size = Size2i(size.x >> 1, size.y >> 1).maxi(1);
615
}
616
617
RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
618
RD::get_singleton()->compute_list_add_barrier(compute_list);
619
RD::get_singleton()->draw_command_end_label();
620
621
RD::get_singleton()->compute_list_end();
622
623
ss_effects.used_full_mips_last_frame = use_full_mips;
624
ss_effects.used_half_size_last_frame = use_half_size;
625
ss_effects.used_mips_last_frame = use_mips;
626
}
627
628
/* SSIL */
629
630
void 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) {
631
ssil_quality = p_quality;
632
ssil_half_size = p_half_size;
633
ssil_adaptive_target = p_adaptive_target;
634
ssil_blur_passes = p_blur_passes;
635
ssil_fadeout_from = p_fadeout_from;
636
ssil_fadeout_to = p_fadeout_to;
637
}
638
639
void 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) {
640
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
641
ERR_FAIL_NULL(uniform_set_cache);
642
643
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
644
if ((ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
645
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
646
}
647
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
648
649
RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
650
651
for (int i = 0; i < 4; i++) {
652
if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
653
continue;
654
}
655
656
RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] }));
657
RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] }));
658
659
ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
660
ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
661
ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
662
ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
663
ssil.gather_push_constant.pass = i;
664
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);
665
RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
666
667
Size2i size;
668
// Calculate size same way as we created the buffer
669
if (ssil_half_size) {
670
size.x = (p_settings.full_screen_size.x + 3) / 4;
671
size.y = (p_settings.full_screen_size.y + 3) / 4;
672
} else {
673
size.x = (p_settings.full_screen_size.x + 1) / 2;
674
size.y = (p_settings.full_screen_size.y + 1) / 2;
675
}
676
677
RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
678
}
679
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
680
}
681
682
void SSEffects::ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings) {
683
if (p_ssil_buffers.half_size != ssil_half_size) {
684
p_render_buffers->clear_context(RB_SCOPE_SSIL);
685
}
686
687
p_ssil_buffers.half_size = ssil_half_size;
688
if (p_ssil_buffers.half_size) {
689
p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
690
p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
691
p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
692
p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
693
} else {
694
p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
695
p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
696
p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
697
p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
698
}
699
700
uint32_t view_count = p_render_buffers->get_view_count();
701
Size2i full_size = Size2i(p_ssil_buffers.buffer_width, p_ssil_buffers.buffer_height);
702
Size2i half_size = Size2i(p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height);
703
704
// We create our intermediate and final results as render buffers.
705
// These are automatically cached and cleaned up when our viewport resizes
706
// or when our viewport gets destroyed.
707
708
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...
709
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);
710
RD::get_singleton()->texture_clear(final, Color(0, 0, 0, 0), 0, 1, 0, view_count);
711
}
712
713
// As we're not clearing these, and render buffers will return the cached texture if it already exists,
714
// we don't first check has_texture here
715
716
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);
717
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);
718
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);
719
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);
720
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);
721
}
722
723
void 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) {
724
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
725
ERR_FAIL_NULL(uniform_set_cache);
726
MaterialStorage *material_storage = MaterialStorage::get_singleton();
727
ERR_FAIL_NULL(material_storage);
728
729
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Indirect Lighting");
730
731
// Obtain our (cached) buffer slices for the view we are rendering.
732
RID last_frame = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, p_view, 0, 1, 6);
733
RID deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);
734
RID deinterleaved_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, 4 * p_view, 0, 4, 1);
735
RID edges = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, 4 * p_view, 0, 4, 1);
736
RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, p_view, 0);
737
RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, p_view, 0);
738
739
RID deinterleaved_slices[4];
740
RID deinterleaved_pong_slices[4];
741
RID edges_slices[4];
742
for (uint32_t i = 0; i < 4; i++) {
743
deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4 + i, 0);
744
deinterleaved_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);
745
edges_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, p_view * 4 + i, 0);
746
}
747
748
//Store projection info before starting the compute list
749
SSILProjectionUniforms projection_uniforms;
750
store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
751
752
RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
753
754
memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
755
756
RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER);
757
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
758
RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
759
760
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
761
{
762
RD::get_singleton()->draw_command_begin_label("Gather Samples");
763
ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
764
ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
765
766
ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
767
ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
768
if (ssil_half_size) {
769
ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
770
ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
771
}
772
ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75;
773
ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75;
774
float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
775
float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
776
ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
777
ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
778
ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
779
ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
780
ssil.gather_push_constant.z_near = p_projection.get_z_near();
781
ssil.gather_push_constant.z_far = p_projection.get_z_far();
782
ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
783
784
ssil.gather_push_constant.radius = p_settings.radius;
785
float radius_near_limit = (p_settings.radius * 1.2f);
786
if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {
787
radius_near_limit *= 1.50f;
788
789
if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
790
ssil.gather_push_constant.radius *= 0.8f;
791
}
792
}
793
radius_near_limit /= tan_half_fov_y;
794
ssil.gather_push_constant.intensity = p_settings.intensity * Math::PI;
795
ssil.gather_push_constant.fade_out_mul = -1.0 / (ssil_fadeout_to - ssil_fadeout_from);
796
ssil.gather_push_constant.fade_out_add = ssil_fadeout_from / (ssil_fadeout_to - ssil_fadeout_from) + 1.0;
797
ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
798
ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
799
ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
800
801
ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);
802
ssil.gather_push_constant.adaptive_sample_limit = ssil_adaptive_target;
803
804
ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1);
805
ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1;
806
807
// We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.
808
// It also ensures that we're reusing the right cached entry in a multiview situation without us having to
809
// remember each instance of the uniform set.
810
811
RID projection_uniform_set;
812
{
813
RD::Uniform u_last_frame;
814
u_last_frame.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
815
u_last_frame.binding = 0;
816
u_last_frame.append_id(default_mipmap_sampler);
817
u_last_frame.append_id(last_frame);
818
819
RD::Uniform u_projection;
820
u_projection.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
821
u_projection.binding = 1;
822
u_projection.append_id(ssil.projection_uniform_buffer);
823
824
projection_uniform_set = uniform_set_cache->get_cache(shader, 3, u_last_frame, u_projection);
825
}
826
827
RID gather_uniform_set;
828
{
829
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);
830
831
RD::Uniform u_depth_texture_view;
832
u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
833
u_depth_texture_view.binding = 0;
834
u_depth_texture_view.append_id(ss_effects.mirror_sampler);
835
u_depth_texture_view.append_id(depth_texture_view);
836
837
RD::Uniform u_normal_buffer;
838
u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;
839
u_normal_buffer.binding = 1;
840
u_normal_buffer.append_id(p_normal_buffer);
841
842
RD::Uniform u_gather_constants_buffer;
843
u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
844
u_gather_constants_buffer.binding = 2;
845
u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);
846
847
gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);
848
}
849
850
RID importance_map_uniform_set;
851
{
852
RD::Uniform u_pong;
853
u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;
854
u_pong.binding = 0;
855
u_pong.append_id(deinterleaved_pong);
856
857
RD::Uniform u_importance_map;
858
u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
859
u_importance_map.binding = 1;
860
u_importance_map.append_id(default_sampler);
861
u_importance_map.append_id(importance_map);
862
863
RD::Uniform u_load_counter;
864
u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
865
u_load_counter.binding = 2;
866
u_load_counter.append_id(ssil.importance_map_load_counter);
867
868
RID shader_adaptive = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER_ADAPTIVE);
869
importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);
870
}
871
872
if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) {
873
RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
874
ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
875
ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
876
ssil.importance_map_push_constant.intensity = p_settings.intensity * Math::PI;
877
878
//base pass
879
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE].get_rid());
880
gather_ssil(compute_list, deinterleaved_pong_slices, edges_slices, p_settings, true, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
881
882
//generate importance map
883
RID gen_imp_shader = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 0);
884
RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));
885
RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));
886
887
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP].get_rid());
888
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);
889
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);
890
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
891
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
892
RD::get_singleton()->compute_list_add_barrier(compute_list);
893
894
// process Importance Map A
895
RID proc_imp_shader_a = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 1);
896
RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
897
RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));
898
899
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA].get_rid());
900
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);
901
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);
902
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
903
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
904
RD::get_singleton()->compute_list_add_barrier(compute_list);
905
906
// process Importance Map B
907
RID proc_imp_shader_b = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2);
908
RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
909
910
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB].get_rid());
911
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);
912
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);
913
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
914
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
915
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
916
RD::get_singleton()->compute_list_add_barrier(compute_list);
917
918
RD::get_singleton()->draw_command_end_label(); // Importance Map
919
920
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE].get_rid());
921
} else {
922
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER].get_rid());
923
}
924
925
gather_ssil(compute_list, deinterleaved_slices, edges_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);
926
RD::get_singleton()->draw_command_end_label(); //Gather
927
}
928
929
{
930
RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
931
ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
932
ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
933
ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
934
935
int blur_passes = ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? ssil_blur_passes : 1;
936
937
shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);
938
939
for (int pass = 0; pass < blur_passes; pass++) {
940
int blur_pipeline = SSIL_BLUR_PASS;
941
if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
942
blur_pipeline = SSIL_BLUR_PASS_SMART;
943
if (pass < blur_passes - 2) {
944
blur_pipeline = SSIL_BLUR_PASS_WIDE;
945
}
946
}
947
948
RID blur_shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, blur_pipeline - SSIL_BLUR_PASS);
949
950
for (int i = 0; i < 4; i++) {
951
if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
952
continue;
953
}
954
955
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline].get_rid());
956
if (pass % 2 == 0) {
957
if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
958
RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_slices[i] }));
959
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);
960
} else {
961
RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_slices[i] }));
962
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);
963
}
964
965
RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_pong_slices[i] }));
966
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_pong_slice), 1);
967
} else {
968
if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
969
RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong_slices[i] }));
970
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);
971
} else {
972
RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_pong_slices[i] }));
973
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);
974
}
975
976
RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_slices[i] }));
977
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_slice), 1);
978
}
979
980
RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges_slices[i] }));
981
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 2, u_edges_slice), 2);
982
983
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
984
985
// Use the size of the actual buffer we're processing here or we won't cover the entire image.
986
int x_groups = p_ssil_buffers.buffer_width;
987
int y_groups = p_ssil_buffers.buffer_height;
988
989
RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
990
}
991
992
RD::get_singleton()->compute_list_add_barrier(compute_list);
993
}
994
995
RD::get_singleton()->draw_command_end_label(); // Blur
996
}
997
998
{
999
RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
1000
ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
1001
ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
1002
ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
1003
ssil.interleave_push_constant.size_modifier = uint32_t(ssil_half_size ? 4 : 2);
1004
1005
int interleave_pipeline = SSIL_INTERLEAVE_HALF;
1006
if (ssil_quality == RS::ENV_SSIL_QUALITY_LOW) {
1007
interleave_pipeline = SSIL_INTERLEAVE;
1008
} else if (ssil_quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
1009
interleave_pipeline = SSIL_INTERLEAVE_SMART;
1010
}
1011
1012
shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);
1013
1014
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline].get_rid());
1015
1016
RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, p_view, 0);
1017
RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ final }));
1018
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);
1019
1020
if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) {
1021
RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved }));
1022
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);
1023
} else {
1024
RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));
1025
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);
1026
}
1027
1028
RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges }));
1029
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);
1030
1031
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
1032
1033
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
1034
RD::get_singleton()->compute_list_add_barrier(compute_list);
1035
RD::get_singleton()->draw_command_end_label(); // Interleave
1036
}
1037
1038
RD::get_singleton()->draw_command_end_label(); // SSIL
1039
1040
RD::get_singleton()->compute_list_end();
1041
1042
int zero[1] = { 0 };
1043
RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
1044
}
1045
1046
/* SSAO */
1047
1048
void 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) {
1049
ssao_quality = p_quality;
1050
ssao_half_size = p_half_size;
1051
ssao_adaptive_target = p_adaptive_target;
1052
ssao_blur_passes = p_blur_passes;
1053
ssao_fadeout_from = p_fadeout_from;
1054
ssao_fadeout_to = p_fadeout_to;
1055
}
1056
1057
void 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) {
1058
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1059
ERR_FAIL_NULL(uniform_set_cache);
1060
1061
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
1062
if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
1063
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
1064
}
1065
1066
RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //
1067
1068
for (int i = 0; i < 4; i++) {
1069
if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
1070
continue;
1071
}
1072
1073
RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, p_ao_slices[i]);
1074
1075
ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
1076
ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
1077
ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
1078
ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
1079
ssao.gather_push_constant.pass = i;
1080
RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);
1081
RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
1082
1083
Size2i size;
1084
// Make sure we use the same size as with which our buffer was created
1085
if (ssao_half_size) {
1086
size.x = (p_settings.full_screen_size.x + 3) / 4;
1087
size.y = (p_settings.full_screen_size.y + 3) / 4;
1088
} else {
1089
size.x = (p_settings.full_screen_size.x + 1) / 2;
1090
size.y = (p_settings.full_screen_size.y + 1) / 2;
1091
}
1092
1093
RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
1094
}
1095
RD::get_singleton()->compute_list_add_barrier(p_compute_list);
1096
}
1097
1098
void SSEffects::ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings) {
1099
if (p_ssao_buffers.half_size != ssao_half_size) {
1100
p_render_buffers->clear_context(RB_SCOPE_SSAO);
1101
}
1102
1103
p_ssao_buffers.half_size = ssao_half_size;
1104
if (ssao_half_size) {
1105
p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
1106
p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
1107
p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
1108
p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
1109
} else {
1110
p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
1111
p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
1112
p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
1113
p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
1114
}
1115
1116
uint32_t view_count = p_render_buffers->get_view_count();
1117
Size2i full_size = Size2i(p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height);
1118
Size2i half_size = Size2i(p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height);
1119
1120
// As we're not clearing these, and render buffers will return the cached texture if it already exists,
1121
// we don't first check has_texture here
1122
1123
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);
1124
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);
1125
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);
1126
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);
1127
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);
1128
}
1129
1130
void 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) {
1131
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1132
ERR_FAIL_NULL(uniform_set_cache);
1133
MaterialStorage *material_storage = MaterialStorage::get_singleton();
1134
ERR_FAIL_NULL(material_storage);
1135
1136
// Obtain our (cached) buffer slices for the view we are rendering.
1137
RID ao_deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);
1138
RID ao_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4, 0, 4, 1);
1139
RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, p_view, 0);
1140
RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, p_view, 0);
1141
RID ao_final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, p_view, 0);
1142
1143
RID ao_deinterleaved_slices[4];
1144
RID ao_pong_slices[4];
1145
for (uint32_t i = 0; i < 4; i++) {
1146
ao_deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4 + i, 0);
1147
ao_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);
1148
}
1149
1150
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1151
memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
1152
/* FIRST PASS */
1153
1154
RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER);
1155
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1156
1157
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Ambient Occlusion");
1158
/* SECOND PASS */
1159
// Sample SSAO
1160
{
1161
RD::get_singleton()->draw_command_begin_label("Gather Samples");
1162
ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
1163
ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
1164
1165
ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;
1166
ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;
1167
if (ssao_half_size) {
1168
ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0;
1169
ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0;
1170
}
1171
ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75;
1172
ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75;
1173
float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
1174
float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
1175
ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
1176
ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
1177
ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
1178
ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
1179
ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
1180
1181
ssao.gather_push_constant.radius = p_settings.radius;
1182
float radius_near_limit = (p_settings.radius * 1.2f);
1183
if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {
1184
radius_near_limit *= 1.50f;
1185
1186
if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
1187
ssao.gather_push_constant.radius *= 0.8f;
1188
}
1189
}
1190
radius_near_limit /= tan_half_fov_y;
1191
ssao.gather_push_constant.intensity = p_settings.intensity;
1192
ssao.gather_push_constant.shadow_power = p_settings.power;
1193
ssao.gather_push_constant.shadow_clamp = 0.98;
1194
ssao.gather_push_constant.fade_out_mul = -1.0 / (ssao_fadeout_to - ssao_fadeout_from);
1195
ssao.gather_push_constant.fade_out_add = ssao_fadeout_from / (ssao_fadeout_to - ssao_fadeout_from) + 1.0;
1196
ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
1197
ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
1198
ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
1199
1200
ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);
1201
ssao.gather_push_constant.adaptive_sample_limit = ssao_adaptive_target;
1202
1203
ssao.gather_push_constant.detail_intensity = p_settings.detail;
1204
ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1);
1205
ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1;
1206
1207
// We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.
1208
// It also ensures that we're reusing the right cached entry in a multiview situation without us having to
1209
// remember each instance of the uniform set.
1210
RID gather_uniform_set;
1211
{
1212
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);
1213
1214
RD::Uniform u_depth_texture_view;
1215
u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
1216
u_depth_texture_view.binding = 0;
1217
u_depth_texture_view.append_id(ss_effects.mirror_sampler);
1218
u_depth_texture_view.append_id(depth_texture_view);
1219
1220
RD::Uniform u_normal_buffer;
1221
u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;
1222
u_normal_buffer.binding = 1;
1223
u_normal_buffer.append_id(p_normal_buffer);
1224
1225
RD::Uniform u_gather_constants_buffer;
1226
u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
1227
u_gather_constants_buffer.binding = 2;
1228
u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);
1229
1230
gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);
1231
}
1232
1233
RID importance_map_uniform_set;
1234
{
1235
RD::Uniform u_pong;
1236
u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;
1237
u_pong.binding = 0;
1238
u_pong.append_id(ao_pong);
1239
1240
RD::Uniform u_importance_map;
1241
u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
1242
u_importance_map.binding = 1;
1243
u_importance_map.append_id(default_sampler);
1244
u_importance_map.append_id(importance_map);
1245
1246
RD::Uniform u_load_counter;
1247
u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
1248
u_load_counter.binding = 2;
1249
u_load_counter.append_id(ssao.importance_map_load_counter);
1250
1251
RID shader_adaptive = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER_ADAPTIVE);
1252
importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);
1253
}
1254
1255
if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) {
1256
RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
1257
ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
1258
ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
1259
ssao.importance_map_push_constant.intensity = p_settings.intensity;
1260
ssao.importance_map_push_constant.power = p_settings.power;
1261
1262
//base pass
1263
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE].get_rid());
1264
gather_ssao(compute_list, ao_pong_slices, p_settings, true, gather_uniform_set, RID());
1265
1266
//generate importance map
1267
RID gen_imp_shader = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 0);
1268
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP].get_rid());
1269
1270
RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));
1271
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);
1272
1273
RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));
1274
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);
1275
1276
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
1277
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
1278
RD::get_singleton()->compute_list_add_barrier(compute_list);
1279
1280
//process importance map A
1281
RID proc_imp_shader_a = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 1);
1282
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA].get_rid());
1283
1284
RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));
1285
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);
1286
1287
RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));
1288
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);
1289
1290
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
1291
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
1292
RD::get_singleton()->compute_list_add_barrier(compute_list);
1293
1294
//process Importance Map B
1295
RID proc_imp_shader_b = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2);
1296
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB].get_rid());
1297
1298
RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));
1299
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);
1300
1301
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);
1302
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
1303
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
1304
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
1305
RD::get_singleton()->compute_list_add_barrier(compute_list);
1306
1307
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE].get_rid());
1308
RD::get_singleton()->draw_command_end_label(); // Importance Map
1309
} else {
1310
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER].get_rid());
1311
}
1312
1313
gather_ssao(compute_list, ao_deinterleaved_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set);
1314
RD::get_singleton()->draw_command_end_label(); // Gather SSAO
1315
}
1316
1317
// /* THIRD PASS */
1318
// // Blur
1319
//
1320
{
1321
RD::get_singleton()->draw_command_begin_label("Edge-Aware Blur");
1322
ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
1323
ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
1324
ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
1325
1326
int blur_passes = ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? ssao_blur_passes : 1;
1327
1328
shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);
1329
1330
for (int pass = 0; pass < blur_passes; pass++) {
1331
int blur_pipeline = SSAO_BLUR_PASS;
1332
if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
1333
if (pass < blur_passes - 2) {
1334
blur_pipeline = SSAO_BLUR_PASS_WIDE;
1335
} else {
1336
blur_pipeline = SSAO_BLUR_PASS_SMART;
1337
}
1338
}
1339
1340
for (int i = 0; i < 4; i++) {
1341
if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
1342
continue;
1343
}
1344
1345
RID blur_shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, blur_pipeline - SSAO_BLUR_PASS);
1346
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline].get_rid());
1347
if (pass % 2 == 0) {
1348
if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
1349
RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved_slices[i] }));
1350
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);
1351
} else {
1352
RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_deinterleaved_slices[i] }));
1353
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);
1354
}
1355
1356
RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_pong_slices[i] }));
1357
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_pong_slices), 1);
1358
} else {
1359
if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
1360
RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong_slices[i] }));
1361
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);
1362
} else {
1363
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] }));
1364
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);
1365
}
1366
1367
RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_deinterleaved_slices[i] }));
1368
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_slices), 1);
1369
}
1370
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
1371
1372
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height, 1);
1373
}
1374
1375
RD::get_singleton()->compute_list_add_barrier(compute_list);
1376
}
1377
RD::get_singleton()->draw_command_end_label(); // Blur
1378
}
1379
1380
/* FOURTH PASS */
1381
// Interleave buffers
1382
// back to full size
1383
{
1384
RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
1385
ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
1386
ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
1387
ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
1388
ssao.interleave_push_constant.size_modifier = uint32_t(ssao_half_size ? 4 : 2);
1389
1390
shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);
1391
1392
int interleave_pipeline = SSAO_INTERLEAVE_HALF;
1393
if (ssao_quality == RS::ENV_SSAO_QUALITY_LOW) {
1394
interleave_pipeline = SSAO_INTERLEAVE;
1395
} else if (ssao_quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
1396
interleave_pipeline = SSAO_INTERLEAVE_SMART;
1397
}
1398
1399
RID interleave_shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, interleave_pipeline - SSAO_INTERLEAVE);
1400
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline].get_rid());
1401
1402
RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_final }));
1403
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 0, u_upscale_buffer), 0);
1404
1405
if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) {
1406
RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved }));
1407
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);
1408
} else {
1409
RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));
1410
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);
1411
}
1412
1413
RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
1414
1415
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
1416
RD::get_singleton()->compute_list_add_barrier(compute_list);
1417
RD::get_singleton()->draw_command_end_label(); // Interleave
1418
}
1419
RD::get_singleton()->draw_command_end_label(); //SSAO
1420
RD::get_singleton()->compute_list_end();
1421
1422
int zero[1] = { 0 };
1423
RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
1424
}
1425
1426
/* Screen Space Reflection */
1427
1428
void SSEffects::ssr_set_half_size(bool p_half_size) {
1429
ssr_half_size = p_half_size;
1430
}
1431
1432
void SSEffects::ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RD::DataFormat p_color_format) {
1433
if (p_ssr_buffers.half_size != ssr_half_size) {
1434
p_render_buffers->clear_context(RB_SCOPE_SSR);
1435
}
1436
1437
Vector2i internal_size = p_render_buffers->get_internal_size();
1438
p_ssr_buffers.size = ssr_half_size ? (internal_size / 2) : internal_size;
1439
1440
uint32_t cur_width = p_ssr_buffers.size.width;
1441
uint32_t cur_height = p_ssr_buffers.size.height;
1442
p_ssr_buffers.mipmaps = 1;
1443
1444
while (cur_width > 1 && cur_height > 1) {
1445
if (cur_width > 1) {
1446
cur_width /= 2;
1447
}
1448
if (cur_height > 1) {
1449
cur_height /= 2;
1450
}
1451
++p_ssr_buffers.mipmaps;
1452
}
1453
1454
p_ssr_buffers.half_size = ssr_half_size;
1455
1456
uint32_t view_count = p_render_buffers->get_view_count();
1457
1458
if (ssr_half_size) {
1459
p_render_buffers->create_texture(RB_SCOPE_SSR, RB_NORMAL_ROUGHNESS, RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, view_count);
1460
}
1461
1462
p_render_buffers->create_texture(RB_SCOPE_SSR, RB_HIZ, RD::DATA_FORMAT_R32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, view_count, p_ssr_buffers.mipmaps);
1463
p_render_buffers->create_texture(RB_SCOPE_SSR, RB_SSR, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, view_count, p_ssr_buffers.mipmaps);
1464
p_render_buffers->create_texture(RB_SCOPE_SSR, RB_MIP_LEVEL, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, view_count);
1465
1466
if (ssr_half_size) {
1467
p_render_buffers->create_texture(RB_SCOPE_SSR, RB_FINAL, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, internal_size, view_count);
1468
}
1469
}
1470
1471
void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RID *p_normal_roughness_slices, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const Projection *p_projections, const Projection *p_reprojections, const Vector3 *p_eye_offsets, RendererRD::CopyEffects &p_copy_effects) {
1472
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1473
ERR_FAIL_NULL(uniform_set_cache);
1474
MaterialStorage *material_storage = MaterialStorage::get_singleton();
1475
ERR_FAIL_NULL(material_storage);
1476
1477
uint32_t view_count = p_render_buffers->get_view_count();
1478
{
1479
// Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders
1480
ScreenSpaceReflectionSceneData scene_data;
1481
1482
if (ssr.ubo.is_null()) {
1483
ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));
1484
}
1485
1486
Projection correction;
1487
correction.set_depth_correction(true);
1488
1489
for (uint32_t v = 0; v < view_count; v++) {
1490
Projection projection = correction * p_projections[v];
1491
1492
store_camera(projection, scene_data.projection[v]);
1493
store_camera(projection.inverse(), scene_data.inv_projection[v]);
1494
store_camera(p_reprojections[v], scene_data.reprojection[v]);
1495
scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
1496
scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
1497
scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
1498
scene_data.eye_offset[v][3] = 0.0f;
1499
}
1500
1501
RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data);
1502
}
1503
1504
RID linear_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1505
RID nearest_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1506
1507
if (ssr_half_size) {
1508
RD::get_singleton()->draw_command_begin_label("SSR Downsample");
1509
1510
for (uint32_t v = 0; v < view_count; v++) {
1511
ScreenSpaceReflectionDownsamplePushConstant push_constant;
1512
push_constant.screen_size[0] = p_ssr_buffers.size.width;
1513
push_constant.screen_size[1] = p_ssr_buffers.size.height;
1514
1515
RID source_depth_texture = p_render_buffers->get_depth_texture(v);
1516
RID dest_depth_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0);
1517
RID dest_normal_roughness_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_NORMAL_ROUGHNESS, v, 0);
1518
1519
Size2i parent_size = RD::get_singleton()->texture_size(source_depth_texture);
1520
bool is_width_odd = (parent_size.width % 2) != 0;
1521
bool is_height_odd = (parent_size.height % 2) != 0;
1522
1523
int32_t downsample_mode;
1524
if (is_width_odd && is_height_odd) {
1525
downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH_AND_HEIGHT;
1526
} else if (is_width_odd) {
1527
downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH;
1528
} else if (is_height_odd) {
1529
downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_HEIGHT;
1530
} else {
1531
downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_DEFAULT;
1532
}
1533
1534
RID downsample_shader = ssr.downsample_shader.version_get_shader(ssr.downsample_shader_version, downsample_mode);
1535
1536
RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ nearest_sampler, source_depth_texture });
1537
RD::Uniform u_source_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>{ nearest_sampler, p_normal_roughness_slices[v] });
1538
RD::Uniform u_dest_depth(RD::UNIFORM_TYPE_IMAGE, 2, dest_depth_texture);
1539
RD::Uniform u_dest_normal_roughness(RD::UNIFORM_TYPE_IMAGE, 3, dest_normal_roughness_texture);
1540
1541
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1542
1543
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.downsample_pipelines[downsample_mode].get_rid());
1544
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(downsample_shader, 0, u_source_depth, u_source_normal_roughness, u_dest_depth, u_dest_normal_roughness), 0);
1545
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));
1546
RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.screen_size[0], push_constant.screen_size[1], 1);
1547
1548
RD::get_singleton()->compute_list_end();
1549
}
1550
1551
RD::get_singleton()->draw_command_end_label();
1552
} else {
1553
RD::get_singleton()->draw_command_begin_label("SSR Copy Depth");
1554
1555
for (uint32_t v = 0; v < view_count; v++) {
1556
RID src_texture = p_render_buffers->get_depth_texture(v);
1557
RID dest_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0);
1558
p_copy_effects.copy_depth_to_rect(src_texture, dest_texture, Rect2i(Vector2i(), p_ssr_buffers.size));
1559
}
1560
1561
RD::get_singleton()->draw_command_end_label();
1562
}
1563
1564
RD::get_singleton()->draw_command_begin_label("SSR HI-Z");
1565
1566
for (uint32_t v = 0; v < view_count; v++) {
1567
for (uint32_t m = 1; m < p_ssr_buffers.mipmaps; m++) {
1568
ScreenSpaceReflectionHizPushConstant push_constant;
1569
push_constant.screen_size[0] = MAX(1, p_ssr_buffers.size.width >> m);
1570
push_constant.screen_size[1] = MAX(1, p_ssr_buffers.size.height >> m);
1571
1572
RID source;
1573
1574
if (!ssr_half_size && m == 1) { // Reuse the depth texture to not create a dependency on the previous depth copy pass.
1575
source = p_render_buffers->get_depth_texture(v);
1576
} else {
1577
source = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, m - 1);
1578
}
1579
1580
RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, m);
1581
1582
Size2i parent_size = RD::get_singleton()->texture_size(source);
1583
bool is_width_odd = (parent_size.width % 2) != 0;
1584
bool is_height_odd = (parent_size.height % 2) != 0;
1585
1586
int32_t hiz_mode;
1587
if (is_width_odd && is_height_odd) {
1588
hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH_AND_HEIGHT;
1589
} else if (is_width_odd) {
1590
hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH;
1591
} else if (is_height_odd) {
1592
hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_ODD_HEIGHT;
1593
} else {
1594
hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_DEFAULT;
1595
}
1596
1597
RID hiz_shader = ssr.hiz_shader.version_get_shader(ssr.hiz_shader_version, hiz_mode);
1598
1599
RD::Uniform u_source(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ nearest_sampler, source });
1600
RD::Uniform u_dest(RD::UNIFORM_TYPE_IMAGE, 1, dest);
1601
1602
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1603
1604
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.hiz_pipelines[hiz_mode].get_rid());
1605
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(hiz_shader, 0, u_source, u_dest), 0);
1606
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));
1607
RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.screen_size[0], push_constant.screen_size[1], 1);
1608
1609
RD::get_singleton()->compute_list_end();
1610
}
1611
}
1612
1613
RD::get_singleton()->draw_command_end_label();
1614
1615
RD::get_singleton()->draw_command_begin_label("SSR Main");
1616
1617
RID ssr_shader = ssr.ssr_shader.version_get_shader(ssr.ssr_shader_version, 0);
1618
1619
for (uint32_t v = 0; v < view_count; v++) {
1620
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1621
1622
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.ssr_pipeline.get_rid());
1623
1624
ScreenSpaceReflectionPushConstant push_constant;
1625
push_constant.screen_size[0] = p_ssr_buffers.size.width;
1626
push_constant.screen_size[1] = p_ssr_buffers.size.height;
1627
push_constant.mipmaps = p_ssr_buffers.mipmaps;
1628
push_constant.num_steps = p_max_steps;
1629
push_constant.curve_fade_in = p_fade_in;
1630
push_constant.distance_fade = p_fade_out;
1631
push_constant.depth_tolerance = p_tolerance;
1632
push_constant.orthogonal = p_projections[v].is_orthogonal();
1633
push_constant.view_index = v;
1634
1635
RID last_frame_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, 0);
1636
if (ssr_half_size && RD::get_singleton()->texture_size(last_frame_texture) != p_ssr_buffers.size) {
1637
// SSIL is likely also enabled. The texture we need is in the second mipmap in this case.
1638
last_frame_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, 1);
1639
}
1640
1641
RID hiz_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0, 1, p_ssr_buffers.mipmaps);
1642
RID normal_roughness_texture = ssr_half_size ? p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_NORMAL_ROUGHNESS, v, 0) : p_normal_roughness_slices[v];
1643
RID ssr_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, 0);
1644
RID mip_level_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_MIP_LEVEL, v, 0);
1645
1646
RD::Uniform u_last_frame(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ linear_sampler, last_frame_texture });
1647
RD::Uniform u_hiz(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>{ nearest_sampler, hiz_texture });
1648
RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 2, Vector<RID>{ nearest_sampler, normal_roughness_texture });
1649
RD::Uniform u_ssr(RD::UNIFORM_TYPE_IMAGE, 3, ssr_texture);
1650
RD::Uniform u_mip_level(RD::UNIFORM_TYPE_IMAGE, 4, mip_level_texture);
1651
RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 5, ssr.ubo);
1652
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(ssr_shader, 0, u_last_frame, u_hiz, u_normal_roughness, u_ssr, u_mip_level, u_scene_data), 0);
1653
1654
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));
1655
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);
1656
1657
RD::get_singleton()->compute_list_end();
1658
}
1659
1660
RD::get_singleton()->draw_command_end_label();
1661
1662
RD::get_singleton()->draw_command_begin_label("SSR Roughness Filter");
1663
1664
RID filter_shader = ssr.filter_shader.version_get_shader(ssr.filter_shader_version, 0);
1665
1666
for (uint32_t v = 0; v < view_count; v++) {
1667
for (uint32_t m = 1; m < p_ssr_buffers.mipmaps; m++) {
1668
ScreenSpaceReflectionFilterPushConstant push_constant;
1669
push_constant.screen_size[0] = MAX(1, p_ssr_buffers.size.width >> m);
1670
push_constant.screen_size[1] = MAX(1, p_ssr_buffers.size.height >> m);
1671
push_constant.mip_level = m;
1672
1673
RID source = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, m - 1);
1674
RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, m);
1675
1676
RD::Uniform u_source(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ linear_sampler, source });
1677
RD::Uniform u_dest(RD::UNIFORM_TYPE_IMAGE, 1, dest);
1678
1679
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1680
1681
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.filter_pipeline.get_rid());
1682
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(filter_shader, 0, u_source, u_dest), 0);
1683
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));
1684
RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.screen_size[0], push_constant.screen_size[1], 1);
1685
1686
RD::get_singleton()->compute_list_end();
1687
}
1688
}
1689
1690
RD::get_singleton()->draw_command_end_label();
1691
1692
if (ssr_half_size) {
1693
RD::get_singleton()->draw_command_begin_label("SSR Resolve");
1694
1695
RID resolve_shader = ssr.resolve_shader.version_get_shader(ssr.resolve_shader_version, 0);
1696
1697
for (uint32_t v = 0; v < view_count; v++) {
1698
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1699
1700
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.resolve_pipeline.get_rid());
1701
1702
Vector2i internal_size = p_render_buffers->get_internal_size();
1703
1704
ScreenSpaceReflectionResolvePushConstant push_constant;
1705
push_constant.screen_size[0] = internal_size.x;
1706
push_constant.screen_size[1] = internal_size.y;
1707
1708
RID depth_texture = p_render_buffers->get_depth_texture(v);
1709
RID depth_half_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0);
1710
RID normal_roughness_half_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_NORMAL_ROUGHNESS, v, 0);
1711
RID ssr_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, 0, 1, p_ssr_buffers.mipmaps);
1712
RID mip_level_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_MIP_LEVEL, v, 0);
1713
RID output_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_FINAL, v, 0);
1714
1715
RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ nearest_sampler, depth_texture });
1716
RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>{ nearest_sampler, p_normal_roughness_slices[v] });
1717
RD::Uniform u_depth_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 2, Vector<RID>{ nearest_sampler, depth_half_texture });
1718
RD::Uniform u_normal_roughness_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 3, Vector<RID>{ nearest_sampler, normal_roughness_half_texture });
1719
RD::Uniform u_ssr(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, Vector<RID>{ linear_sampler, ssr_texture });
1720
RD::Uniform u_mip_level(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 5, Vector<RID>{ nearest_sampler, mip_level_texture });
1721
RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 6, output_texture);
1722
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(resolve_shader, 0, u_depth, u_normal_roughness, u_depth_half, u_normal_roughness_half, u_ssr, u_mip_level, u_output), 0);
1723
1724
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));
1725
RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.width, internal_size.height, 1);
1726
1727
RD::get_singleton()->compute_list_end();
1728
}
1729
1730
RD::get_singleton()->draw_command_end_label();
1731
}
1732
}
1733
1734
/* Subsurface scattering */
1735
1736
void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
1737
sss_quality = p_quality;
1738
}
1739
1740
RS::SubSurfaceScatteringQuality SSEffects::sss_get_quality() const {
1741
return sss_quality;
1742
}
1743
1744
void SSEffects::sss_set_scale(float p_scale, float p_depth_scale) {
1745
sss_scale = p_scale;
1746
sss_depth_scale = p_depth_scale;
1747
}
1748
1749
void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size) {
1750
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
1751
ERR_FAIL_NULL(uniform_set_cache);
1752
MaterialStorage *material_storage = MaterialStorage::get_singleton();
1753
ERR_FAIL_NULL(material_storage);
1754
1755
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
1756
1757
// Our intermediate buffer is only created if we haven't created it already.
1758
RD::DataFormat format = p_render_buffers->get_base_data_format();
1759
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
1760
uint32_t layers = 1; // We only need one layer, we're handling one view at a time
1761
uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);
1762
RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);
1763
1764
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
1765
p.normal /= p.d;
1766
float unit_size = p.normal.x;
1767
1768
{ //scale color and depth to half
1769
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
1770
1771
sss.push_constant.camera_z_far = p_camera.get_z_far();
1772
sss.push_constant.camera_z_near = p_camera.get_z_near();
1773
sss.push_constant.orthogonal = p_camera.is_orthogonal();
1774
sss.push_constant.unit_size = unit_size;
1775
sss.push_constant.screen_size[0] = p_screen_size.x;
1776
sss.push_constant.screen_size[1] = p_screen_size.y;
1777
sss.push_constant.vertical = false;
1778
sss.push_constant.scale = sss_scale;
1779
sss.push_constant.depth_scale = sss_depth_scale;
1780
1781
RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1);
1782
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1].get_rid());
1783
1784
RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
1785
RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
1786
RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));
1787
RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
1788
RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));
1789
1790
// horizontal
1791
1792
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);
1793
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
1794
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
1795
1796
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
1797
1798
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
1799
1800
RD::get_singleton()->compute_list_add_barrier(compute_list);
1801
1802
// vertical
1803
1804
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);
1805
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);
1806
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
1807
1808
sss.push_constant.vertical = true;
1809
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
1810
1811
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
1812
1813
RD::get_singleton()->compute_list_end();
1814
}
1815
}
1816
1817