Path: blob/master/servers/rendering/renderer_rd/effects/ss_effects.cpp
10279 views
/**************************************************************************/1/* ss_effects.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "ss_effects.h"3132#include "core/config/project_settings.h"33#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"34#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"35#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"3637using namespace RendererRD;3839SSEffects *SSEffects::singleton = nullptr;4041static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {42for (int i = 0; i < 4; i++) {43for (int j = 0; j < 4; j++) {44p_array[i * 4 + j] = p_mtx.columns[i][j];45}46}47}4849SSEffects::SSEffects() {50singleton = this;5152// Initialize depth buffer for screen space effects53{54Vector<String> downsampler_modes;55downsampler_modes.push_back("\n");56downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");57downsampler_modes.push_back("\n#define GENERATE_MIPS\n");58downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");59downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");60downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");61downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");6263ss_effects.downsample_shader.initialize(downsampler_modes);6465ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();6667for (int i = 0; i < SS_EFFECTS_MAX; i++) {68ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));69}7071ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));72SSEffectsGatherConstants gather_constants;7374const int sub_pass_count = 5;75for (int pass = 0; pass < 4; pass++) {76for (int subPass = 0; subPass < sub_pass_count; subPass++) {77int a = pass;7879int spmap[5]{ 0, 1, 4, 3, 2 };80int b = spmap[subPass];8182float ca, sa;83float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math::PI * 0.5f;8485ca = Math::cos(angle0);86sa = Math::sin(angle0);8788float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;8990gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;91gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;92gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;93gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;94}95}9697RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);98}99100// Initialize Screen Space Indirect Lighting (SSIL)101ssil_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"));102103{104Vector<String> ssil_modes;105ssil_modes.push_back("\n");106ssil_modes.push_back("\n#define SSIL_BASE\n");107ssil_modes.push_back("\n#define ADAPTIVE\n");108109ssil.gather_shader.initialize(ssil_modes);110111ssil.gather_shader_version = ssil.gather_shader.version_create();112113for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {114ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));115}116ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));117}118119{120Vector<String> ssil_modes;121ssil_modes.push_back("\n#define GENERATE_MAP\n");122ssil_modes.push_back("\n#define PROCESS_MAPA\n");123ssil_modes.push_back("\n#define PROCESS_MAPB\n");124125ssil.importance_map_shader.initialize(ssil_modes);126127ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();128129for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {130ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));131}132ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));133int zero[1] = { 0 };134RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);135RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");136137Vector<RD::Uniform> uniforms;138{139RD::Uniform u;140u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;141u.binding = 0;142u.append_id(ssil.importance_map_load_counter);143uniforms.push_back(u);144}145ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);146RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");147}148149{150Vector<String> ssil_modes;151ssil_modes.push_back("\n#define MODE_NON_SMART\n");152ssil_modes.push_back("\n#define MODE_SMART\n");153ssil_modes.push_back("\n#define MODE_WIDE\n");154155ssil.blur_shader.initialize(ssil_modes);156157ssil.blur_shader_version = ssil.blur_shader.version_create();158for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {159ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));160}161}162163{164Vector<String> ssil_modes;165ssil_modes.push_back("\n#define MODE_NON_SMART\n");166ssil_modes.push_back("\n#define MODE_SMART\n");167ssil_modes.push_back("\n#define MODE_HALF\n");168169ssil.interleave_shader.initialize(ssil_modes);170171ssil.interleave_shader_version = ssil.interleave_shader.version_create();172for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {173ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));174}175}176177// Initialize Screen Space Ambient Occlusion (SSAO)178ssao_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"));179180{181RD::SamplerState sampler;182sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;183sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;184sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;185sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;186sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;187sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;188sampler.max_lod = 4;189190uint32_t pipeline = 0;191{192Vector<String> ssao_modes;193194ssao_modes.push_back("\n");195ssao_modes.push_back("\n#define SSAO_BASE\n");196ssao_modes.push_back("\n#define ADAPTIVE\n");197198ssao.gather_shader.initialize(ssao_modes);199200ssao.gather_shader_version = ssao.gather_shader.version_create();201202for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {203ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));204pipeline++;205}206}207208{209Vector<String> ssao_modes;210ssao_modes.push_back("\n#define GENERATE_MAP\n");211ssao_modes.push_back("\n#define PROCESS_MAPA\n");212ssao_modes.push_back("\n#define PROCESS_MAPB\n");213214ssao.importance_map_shader.initialize(ssao_modes);215216ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();217218for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {219ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));220221pipeline++;222}223224ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));225int zero[1] = { 0 };226RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);227RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");228229Vector<RD::Uniform> uniforms;230{231RD::Uniform u;232u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;233u.binding = 0;234u.append_id(ssao.importance_map_load_counter);235uniforms.push_back(u);236}237ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);238RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");239}240241{242Vector<String> ssao_modes;243ssao_modes.push_back("\n#define MODE_NON_SMART\n");244ssao_modes.push_back("\n#define MODE_SMART\n");245ssao_modes.push_back("\n#define MODE_WIDE\n");246247ssao.blur_shader.initialize(ssao_modes);248249ssao.blur_shader_version = ssao.blur_shader.version_create();250251for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {252ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));253254pipeline++;255}256}257258{259Vector<String> ssao_modes;260ssao_modes.push_back("\n#define MODE_NON_SMART\n");261ssao_modes.push_back("\n#define MODE_SMART\n");262ssao_modes.push_back("\n#define MODE_HALF\n");263264ssao.interleave_shader.initialize(ssao_modes);265266ssao.interleave_shader_version = ssao.interleave_shader.version_create();267for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {268ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));269RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));270pipeline++;271}272}273274ERR_FAIL_COND(pipeline != SSAO_MAX);275276ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);277}278279// Screen Space Reflections280ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality")));281282{283Vector<RD::PipelineSpecializationConstant> specialization_constants;284285{286RD::PipelineSpecializationConstant sc;287sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;288sc.constant_id = 0; // SSR_USE_FULL_PROJECTION_MATRIX289sc.bool_value = false;290specialization_constants.push_back(sc);291}292293{294Vector<String> ssr_scale_modes;295ssr_scale_modes.push_back("\n");296297ssr_scale.shader.initialize(ssr_scale_modes);298ssr_scale.shader_version = ssr_scale.shader.version_create();299300for (int v = 0; v < SSR_VARIATIONS; v++) {301specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;302ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants);303}304}305306{307Vector<String> ssr_modes;308ssr_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_NORMAL309ssr_modes.push_back("\n#define MODE_ROUGH\n"); // SCREEN_SPACE_REFLECTION_ROUGH310311ssr.shader.initialize(ssr_modes);312ssr.shader_version = ssr.shader.version_create();313314for (int v = 0; v < SSR_VARIATIONS; v++) {315specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;316for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {317ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants);318}319}320}321322{323Vector<String> ssr_filter_modes;324ssr_filter_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL325ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); // SCREEN_SPACE_REFLECTION_FILTER_VERTICAL326327ssr_filter.shader.initialize(ssr_filter_modes);328ssr_filter.shader_version = ssr_filter.shader.version_create();329330for (int v = 0; v < SSR_VARIATIONS; v++) {331specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;332for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {333ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants);334}335}336}337}338339// Subsurface scattering340sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));341sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");342sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");343344{345Vector<String> sss_modes;346sss_modes.push_back("\n#define USE_11_SAMPLES\n");347sss_modes.push_back("\n#define USE_17_SAMPLES\n");348sss_modes.push_back("\n#define USE_25_SAMPLES\n");349350sss.shader.initialize(sss_modes);351352sss.shader_version = sss.shader.version_create();353354for (int i = 0; i < sss_modes.size(); i++) {355sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));356}357}358}359360SSEffects::~SSEffects() {361{362// Cleanup SS Reflections363ssr.shader.version_free(ssr.shader_version);364ssr_filter.shader.version_free(ssr_filter.shader_version);365ssr_scale.shader.version_free(ssr_scale.shader_version);366367if (ssr.ubo.is_valid()) {368RD::get_singleton()->free(ssr.ubo);369}370}371372{373// Cleanup SS downsampler374ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);375376RD::get_singleton()->free(ss_effects.mirror_sampler);377RD::get_singleton()->free(ss_effects.gather_constants_buffer);378}379380{381// Cleanup SSIL382ssil.blur_shader.version_free(ssil.blur_shader_version);383ssil.gather_shader.version_free(ssil.gather_shader_version);384ssil.interleave_shader.version_free(ssil.interleave_shader_version);385ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);386387RD::get_singleton()->free(ssil.importance_map_load_counter);388RD::get_singleton()->free(ssil.projection_uniform_buffer);389}390391{392// Cleanup SSAO393ssao.blur_shader.version_free(ssao.blur_shader_version);394ssao.gather_shader.version_free(ssao.gather_shader_version);395ssao.interleave_shader.version_free(ssao.interleave_shader_version);396ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);397398RD::get_singleton()->free(ssao.importance_map_load_counter);399}400401{402// Cleanup Subsurface scattering403sss.shader.version_free(sss.shader_version);404}405406singleton = nullptr;407}408409/* SS Downsampler */410411void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection) {412UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();413ERR_FAIL_NULL(uniform_set_cache);414MaterialStorage *material_storage = MaterialStorage::get_singleton();415ERR_FAIL_NULL(material_storage);416417uint32_t view_count = p_render_buffers->get_view_count();418Size2i full_screen_size = p_render_buffers->get_internal_size();419Size2i size((full_screen_size.x + 1) / 2, (full_screen_size.y + 1) / 2);420421// Make sure our buffers exist, buffers are automatically cleared if view count or size changes.422if (!p_render_buffers->has_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH)) {423p_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);424}425426// Downsample and deinterleave the depth buffer for SSAO and SSIL427RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();428429int downsample_mode = SS_EFFECTS_DOWNSAMPLE;430bool use_mips = ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;431432if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {433downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;434} else if (use_mips) {435downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;436}437438bool use_half_size = false;439bool use_full_mips = false;440441if (ssao_half_size && ssil_half_size) {442downsample_mode++;443use_half_size = true;444} else if (ssao_half_size != ssil_half_size) {445if (use_mips) {446downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;447use_full_mips = true;448} else {449// Only need the first two mipmaps, but the cost to generate the next two is trivial450// TODO investigate the benefit of a shader version to generate only 2 mips451downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;452use_mips = true;453}454}455456RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);457int depth_index = use_half_size ? 1 : 0;458459RD::get_singleton()->draw_command_begin_label("Downsample Depth");460461RID downsample_uniform_set;462if (use_mips) {463// Grab our downsample uniform set from cache, these are automatically cleaned up if the depth textures are cleared.464// This also ensures we can switch between left eye and right eye uniform sets without recreating the uniform twice a frame.465thread_local LocalVector<RD::Uniform> u_depths;466u_depths.clear();467468// Note, use_full_mips is true if either SSAO or SSIL uses half size, but the other full size and we're using mips.469// That means we're filling all 5 levels.470// In this scenario `depth_index` will be 0.471for (int i = 0; i < (use_full_mips ? 4 : 3); i++) {472RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index + i + 1, 4, 1);473474RD::Uniform u_depth;475u_depth.uniform_type = RD::UNIFORM_TYPE_IMAGE;476u_depth.binding = i;477u_depth.append_id(depth_mipmap);478u_depths.push_back(u_depth);479}480481// This before only used SS_EFFECTS_DOWNSAMPLE_MIPMAP or SS_EFFECTS_DOWNSAMPLE_FULL_MIPS482downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);483}484485Projection correction;486correction.set_depth_correction(false);487Projection temp = correction * p_projection;488489float depth_linearize_mul = -temp.columns[3][2];490float depth_linearize_add = temp.columns[2][2];491if (depth_linearize_mul * depth_linearize_add < 0) {492depth_linearize_add = -depth_linearize_add;493}494495ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();496ss_effects.downsample_push_constant.z_near = depth_linearize_mul;497ss_effects.downsample_push_constant.z_far = depth_linearize_add;498if (ss_effects.downsample_push_constant.orthogonal) {499ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();500ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();501}502ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / full_screen_size.x;503ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / full_screen_size.y;504ss_effects.downsample_push_constant.radius_sq = 1.0;505506RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);507508RID depth_texture = p_render_buffers->get_depth_texture(p_view);509RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index, 4, 1);510511RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_texture }));512RD::Uniform u_depth_mipmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_mipmap }));513514RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]);515RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);516RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmap), 1);517if (use_mips) {518RD::get_singleton()->compute_list_bind_uniform_set(compute_list, downsample_uniform_set, 2);519}520RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));521522if (use_half_size) {523size = Size2i(size.x >> 1, size.y >> 1).maxi(1);524}525526RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);527RD::get_singleton()->compute_list_add_barrier(compute_list);528RD::get_singleton()->draw_command_end_label();529530RD::get_singleton()->compute_list_end();531532ss_effects.used_full_mips_last_frame = use_full_mips;533ss_effects.used_half_size_last_frame = use_half_size;534ss_effects.used_mips_last_frame = use_mips;535}536537/* SSIL */538539void 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) {540ssil_quality = p_quality;541ssil_half_size = p_half_size;542ssil_adaptive_target = p_adaptive_target;543ssil_blur_passes = p_blur_passes;544ssil_fadeout_from = p_fadeout_from;545ssil_fadeout_to = p_fadeout_to;546}547548void 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) {549UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();550ERR_FAIL_NULL(uniform_set_cache);551552RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);553if ((ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {554RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);555}556RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);557558RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);559560for (int i = 0; i < 4; i++) {561if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {562continue;563}564565RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] }));566RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] }));567568ssil.gather_push_constant.pass_coord_offset[0] = i % 2;569ssil.gather_push_constant.pass_coord_offset[1] = i / 2;570ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;571ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;572ssil.gather_push_constant.pass = i;573RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2);574RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));575576Size2i size;577// Calculate size same way as we created the buffer578if (ssil_half_size) {579size.x = (p_settings.full_screen_size.x + 3) / 4;580size.y = (p_settings.full_screen_size.y + 3) / 4;581} else {582size.x = (p_settings.full_screen_size.x + 1) / 2;583size.y = (p_settings.full_screen_size.y + 1) / 2;584}585586RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);587}588RD::get_singleton()->compute_list_add_barrier(p_compute_list);589}590591void SSEffects::ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings) {592if (p_ssil_buffers.half_size != ssil_half_size) {593p_render_buffers->clear_context(RB_SCOPE_SSIL);594}595596p_ssil_buffers.half_size = ssil_half_size;597if (p_ssil_buffers.half_size) {598p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;599p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;600p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;601p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;602} else {603p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;604p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;605p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;606p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;607}608609uint32_t view_count = p_render_buffers->get_view_count();610Size2i full_size = Size2i(p_ssil_buffers.buffer_width, p_ssil_buffers.buffer_height);611Size2i half_size = Size2i(p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height);612613// We create our intermediate and final results as render buffers.614// These are automatically cached and cleaned up when our viewport resizes615// or when our viewport gets destroyed.616617if (!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...618RID 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);619RD::get_singleton()->texture_clear(final, Color(0, 0, 0, 0), 0, 1, 0, view_count);620}621622if (!p_render_buffers->has_texture(RB_SCOPE_SSIL, RB_LAST_FRAME)) {623RID last_frame = p_render_buffers->create_texture(RB_SCOPE_SSIL, RB_LAST_FRAME, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT, RD::TEXTURE_SAMPLES_1, p_settings.full_screen_size, 0, 6);624RD::get_singleton()->texture_clear(last_frame, Color(0, 0, 0, 0), 0, 6, 0, view_count);625}626627// As we're not clearing these, and render buffers will return the cached texture if it already exists,628// we don't first check has_texture here629630p_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);631p_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);632p_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);633p_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);634p_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);635}636637void 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) {638UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();639ERR_FAIL_NULL(uniform_set_cache);640MaterialStorage *material_storage = MaterialStorage::get_singleton();641ERR_FAIL_NULL(material_storage);642643RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");644645// Obtain our (cached) buffer slices for the view we are rendering.646RID last_frame = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_LAST_FRAME, p_view, 0, 1, 6);647RID deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);648RID deinterleaved_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, 4 * p_view, 0, 4, 1);649RID edges = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, 4 * p_view, 0, 4, 1);650RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, p_view, 0);651RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, p_view, 0);652653RID deinterleaved_slices[4];654RID deinterleaved_pong_slices[4];655RID edges_slices[4];656for (uint32_t i = 0; i < 4; i++) {657deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4 + i, 0);658deinterleaved_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);659edges_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, p_view * 4 + i, 0);660}661662//Store projection info before starting the compute list663SSILProjectionUniforms projection_uniforms;664store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);665666RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);667668memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));669670RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER);671RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);672RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);673674RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();675{676RD::get_singleton()->draw_command_begin_label("Gather Samples");677ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;678ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;679680ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;681ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;682if (ssil_half_size) {683ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0;684ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0;685}686ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75;687ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75;688float tan_half_fov_x = 1.0 / p_projection.columns[0][0];689float tan_half_fov_y = 1.0 / p_projection.columns[1][1];690ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;691ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;692ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;693ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;694ssil.gather_push_constant.z_near = p_projection.get_z_near();695ssil.gather_push_constant.z_far = p_projection.get_z_far();696ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();697698ssil.gather_push_constant.radius = p_settings.radius;699float radius_near_limit = (p_settings.radius * 1.2f);700if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {701radius_near_limit *= 1.50f;702703if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {704ssil.gather_push_constant.radius *= 0.8f;705}706}707radius_near_limit /= tan_half_fov_y;708ssil.gather_push_constant.intensity = p_settings.intensity * Math::PI;709ssil.gather_push_constant.fade_out_mul = -1.0 / (ssil_fadeout_to - ssil_fadeout_from);710ssil.gather_push_constant.fade_out_add = ssil_fadeout_from / (ssil_fadeout_to - ssil_fadeout_from) + 1.0;711ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;712ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;713ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;714715ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);716ssil.gather_push_constant.adaptive_sample_limit = ssil_adaptive_target;717718ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1);719ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1;720721// We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.722// It also ensures that we're reusing the right cached entry in a multiview situation without us having to723// remember each instance of the uniform set.724725RID projection_uniform_set;726{727RD::Uniform u_last_frame;728u_last_frame.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;729u_last_frame.binding = 0;730u_last_frame.append_id(default_mipmap_sampler);731u_last_frame.append_id(last_frame);732733RD::Uniform u_projection;734u_projection.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;735u_projection.binding = 1;736u_projection.append_id(ssil.projection_uniform_buffer);737738projection_uniform_set = uniform_set_cache->get_cache(shader, 3, u_last_frame, u_projection);739}740741RID gather_uniform_set;742{743RID 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);744745RD::Uniform u_depth_texture_view;746u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;747u_depth_texture_view.binding = 0;748u_depth_texture_view.append_id(ss_effects.mirror_sampler);749u_depth_texture_view.append_id(depth_texture_view);750751RD::Uniform u_normal_buffer;752u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;753u_normal_buffer.binding = 1;754u_normal_buffer.append_id(p_normal_buffer);755756RD::Uniform u_gather_constants_buffer;757u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;758u_gather_constants_buffer.binding = 2;759u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);760761gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);762}763764RID importance_map_uniform_set;765{766RD::Uniform u_pong;767u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;768u_pong.binding = 0;769u_pong.append_id(deinterleaved_pong);770771RD::Uniform u_importance_map;772u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;773u_importance_map.binding = 1;774u_importance_map.append_id(default_sampler);775u_importance_map.append_id(importance_map);776777RD::Uniform u_load_counter;778u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;779u_load_counter.binding = 2;780u_load_counter.append_id(ssil.importance_map_load_counter);781782RID shader_adaptive = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER_ADAPTIVE);783importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);784}785786if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) {787RD::get_singleton()->draw_command_begin_label("Generate Importance Map");788ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;789ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;790ssil.importance_map_push_constant.intensity = p_settings.intensity * Math::PI;791792//base pass793RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);794gather_ssil(compute_list, deinterleaved_pong_slices, edges_slices, p_settings, true, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);795796//generate importance map797RID gen_imp_shader = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 0);798RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));799RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));800801RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);802RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ssil_pong_with_sampler), 0);803RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);804RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));805RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);806RD::get_singleton()->compute_list_add_barrier(compute_list);807808// process Importance Map A809RID proc_imp_shader_a = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 1);810RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));811RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));812813RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);814RD::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);815RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);816RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));817RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);818RD::get_singleton()->compute_list_add_barrier(compute_list);819820// process Importance Map B821RID proc_imp_shader_b = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2);822RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));823824RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);825RD::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);826RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);827RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);828RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));829RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);830RD::get_singleton()->compute_list_add_barrier(compute_list);831832RD::get_singleton()->draw_command_end_label(); // Importance Map833834RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);835} else {836RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);837}838839gather_ssil(compute_list, deinterleaved_slices, edges_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);840RD::get_singleton()->draw_command_end_label(); //Gather841}842843{844RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");845ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;846ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;847ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;848849int blur_passes = ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? ssil_blur_passes : 1;850851shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);852853for (int pass = 0; pass < blur_passes; pass++) {854int blur_pipeline = SSIL_BLUR_PASS;855if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {856blur_pipeline = SSIL_BLUR_PASS_SMART;857if (pass < blur_passes - 2) {858blur_pipeline = SSIL_BLUR_PASS_WIDE;859}860}861862RID blur_shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, blur_pipeline - SSIL_BLUR_PASS);863864for (int i = 0; i < 4; i++) {865if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {866continue;867}868869RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);870if (pass % 2 == 0) {871if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {872RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_slices[i] }));873RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);874} else {875RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_slices[i] }));876RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);877}878879RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_pong_slices[i] }));880RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_pong_slice), 1);881} else {882if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {883RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong_slices[i] }));884RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);885} else {886RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_pong_slices[i] }));887RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);888}889890RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_slices[i] }));891RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_slice), 1);892}893894RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges_slices[i] }));895RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 2, u_edges_slice), 2);896897RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));898899// Use the size of the actual buffer we're processing here or we won't cover the entire image.900int x_groups = p_ssil_buffers.buffer_width;901int y_groups = p_ssil_buffers.buffer_height;902903RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);904}905906RD::get_singleton()->compute_list_add_barrier(compute_list);907}908909RD::get_singleton()->draw_command_end_label(); // Blur910}911912{913RD::get_singleton()->draw_command_begin_label("Interleave Buffers");914ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;915ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;916ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;917ssil.interleave_push_constant.size_modifier = uint32_t(ssil_half_size ? 4 : 2);918919int interleave_pipeline = SSIL_INTERLEAVE_HALF;920if (ssil_quality == RS::ENV_SSIL_QUALITY_LOW) {921interleave_pipeline = SSIL_INTERLEAVE;922} else if (ssil_quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {923interleave_pipeline = SSIL_INTERLEAVE_SMART;924}925926shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);927928RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);929930RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, p_view, 0);931RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ final }));932RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);933934if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) {935RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved }));936RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);937} else {938RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));939RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);940}941942RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges }));943RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);944945RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));946947RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);948RD::get_singleton()->compute_list_add_barrier(compute_list);949RD::get_singleton()->draw_command_end_label(); // Interleave950}951952RD::get_singleton()->draw_command_end_label(); // SSIL953954RD::get_singleton()->compute_list_end();955956int zero[1] = { 0 };957RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);958}959960/* SSAO */961962void 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) {963ssao_quality = p_quality;964ssao_half_size = p_half_size;965ssao_adaptive_target = p_adaptive_target;966ssao_blur_passes = p_blur_passes;967ssao_fadeout_from = p_fadeout_from;968ssao_fadeout_to = p_fadeout_to;969}970971void 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) {972UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();973ERR_FAIL_NULL(uniform_set_cache);974975RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);976if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {977RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);978}979980RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //981982for (int i = 0; i < 4; i++) {983if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {984continue;985}986987RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, p_ao_slices[i]);988989ssao.gather_push_constant.pass_coord_offset[0] = i % 2;990ssao.gather_push_constant.pass_coord_offset[1] = i / 2;991ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;992ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;993ssao.gather_push_constant.pass = i;994RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);995RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));996997Size2i size;998// Make sure we use the same size as with which our buffer was created999if (ssao_half_size) {1000size.x = (p_settings.full_screen_size.x + 3) / 4;1001size.y = (p_settings.full_screen_size.y + 3) / 4;1002} else {1003size.x = (p_settings.full_screen_size.x + 1) / 2;1004size.y = (p_settings.full_screen_size.y + 1) / 2;1005}10061007RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);1008}1009RD::get_singleton()->compute_list_add_barrier(p_compute_list);1010}10111012void SSEffects::ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings) {1013if (p_ssao_buffers.half_size != ssao_half_size) {1014p_render_buffers->clear_context(RB_SCOPE_SSAO);1015}10161017p_ssao_buffers.half_size = ssao_half_size;1018if (ssao_half_size) {1019p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;1020p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;1021p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;1022p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;1023} else {1024p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;1025p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;1026p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;1027p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;1028}10291030uint32_t view_count = p_render_buffers->get_view_count();1031Size2i full_size = Size2i(p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height);1032Size2i half_size = Size2i(p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height);10331034// As we're not clearing these, and render buffers will return the cached texture if it already exists,1035// we don't first check has_texture here10361037p_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);1038p_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);1039p_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);1040p_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);1041p_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);1042}10431044void 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) {1045UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();1046ERR_FAIL_NULL(uniform_set_cache);1047MaterialStorage *material_storage = MaterialStorage::get_singleton();1048ERR_FAIL_NULL(material_storage);10491050// Obtain our (cached) buffer slices for the view we are rendering.1051RID ao_deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);1052RID ao_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4, 0, 4, 1);1053RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, p_view, 0);1054RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, p_view, 0);1055RID ao_final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, p_view, 0);10561057RID ao_deinterleaved_slices[4];1058RID ao_pong_slices[4];1059for (uint32_t i = 0; i < 4; i++) {1060ao_deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4 + i, 0);1061ao_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);1062}10631064RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();1065memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));1066/* FIRST PASS */10671068RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER);1069RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);10701071RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");1072/* SECOND PASS */1073// Sample SSAO1074{1075RD::get_singleton()->draw_command_begin_label("Gather Samples");1076ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;1077ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;10781079ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;1080ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;1081if (ssao_half_size) {1082ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0;1083ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0;1084}1085ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75;1086ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75;1087float tan_half_fov_x = 1.0 / p_projection.columns[0][0];1088float tan_half_fov_y = 1.0 / p_projection.columns[1][1];1089ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;1090ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;1091ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;1092ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;1093ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();10941095ssao.gather_push_constant.radius = p_settings.radius;1096float radius_near_limit = (p_settings.radius * 1.2f);1097if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {1098radius_near_limit *= 1.50f;10991100if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {1101ssao.gather_push_constant.radius *= 0.8f;1102}1103}1104radius_near_limit /= tan_half_fov_y;1105ssao.gather_push_constant.intensity = p_settings.intensity;1106ssao.gather_push_constant.shadow_power = p_settings.power;1107ssao.gather_push_constant.shadow_clamp = 0.98;1108ssao.gather_push_constant.fade_out_mul = -1.0 / (ssao_fadeout_to - ssao_fadeout_from);1109ssao.gather_push_constant.fade_out_add = ssao_fadeout_from / (ssao_fadeout_to - ssao_fadeout_from) + 1.0;1110ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;1111ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;1112ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;11131114ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);1115ssao.gather_push_constant.adaptive_sample_limit = ssao_adaptive_target;11161117ssao.gather_push_constant.detail_intensity = p_settings.detail;1118ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1);1119ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1;11201121// We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.1122// It also ensures that we're reusing the right cached entry in a multiview situation without us having to1123// remember each instance of the uniform set.1124RID gather_uniform_set;1125{1126RID 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);11271128RD::Uniform u_depth_texture_view;1129u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;1130u_depth_texture_view.binding = 0;1131u_depth_texture_view.append_id(ss_effects.mirror_sampler);1132u_depth_texture_view.append_id(depth_texture_view);11331134RD::Uniform u_normal_buffer;1135u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;1136u_normal_buffer.binding = 1;1137u_normal_buffer.append_id(p_normal_buffer);11381139RD::Uniform u_gather_constants_buffer;1140u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;1141u_gather_constants_buffer.binding = 2;1142u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);11431144gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);1145}11461147RID importance_map_uniform_set;1148{1149RD::Uniform u_pong;1150u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;1151u_pong.binding = 0;1152u_pong.append_id(ao_pong);11531154RD::Uniform u_importance_map;1155u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;1156u_importance_map.binding = 1;1157u_importance_map.append_id(default_sampler);1158u_importance_map.append_id(importance_map);11591160RD::Uniform u_load_counter;1161u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1162u_load_counter.binding = 2;1163u_load_counter.append_id(ssao.importance_map_load_counter);11641165RID shader_adaptive = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER_ADAPTIVE);1166importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);1167}11681169if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) {1170RD::get_singleton()->draw_command_begin_label("Generate Importance Map");1171ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;1172ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;1173ssao.importance_map_push_constant.intensity = p_settings.intensity;1174ssao.importance_map_push_constant.power = p_settings.power;11751176//base pass1177RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);1178gather_ssao(compute_list, ao_pong_slices, p_settings, true, gather_uniform_set, RID());11791180//generate importance map1181RID gen_imp_shader = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 0);1182RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);11831184RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));1185RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ao_pong_with_sampler), 0);11861187RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));1188RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);11891190RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));1191RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);1192RD::get_singleton()->compute_list_add_barrier(compute_list);11931194//process importance map A1195RID proc_imp_shader_a = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 1);1196RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);11971198RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));1199RD::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);12001201RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));1202RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);12031204RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));1205RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);1206RD::get_singleton()->compute_list_add_barrier(compute_list);12071208//process Importance Map B1209RID proc_imp_shader_b = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2);1210RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);12111212RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));1213RD::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);12141215RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);1216RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);1217RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));1218RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);1219RD::get_singleton()->compute_list_add_barrier(compute_list);12201221RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);1222RD::get_singleton()->draw_command_end_label(); // Importance Map1223} else {1224RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);1225}12261227gather_ssao(compute_list, ao_deinterleaved_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set);1228RD::get_singleton()->draw_command_end_label(); // Gather SSAO1229}12301231// /* THIRD PASS */1232// // Blur1233//1234{1235RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");1236ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;1237ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;1238ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;12391240int blur_passes = ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? ssao_blur_passes : 1;12411242shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);12431244for (int pass = 0; pass < blur_passes; pass++) {1245int blur_pipeline = SSAO_BLUR_PASS;1246if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {1247if (pass < blur_passes - 2) {1248blur_pipeline = SSAO_BLUR_PASS_WIDE;1249} else {1250blur_pipeline = SSAO_BLUR_PASS_SMART;1251}1252}12531254for (int i = 0; i < 4; i++) {1255if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {1256continue;1257}12581259RID blur_shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, blur_pipeline - SSAO_BLUR_PASS);1260RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);1261if (pass % 2 == 0) {1262if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {1263RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved_slices[i] }));1264RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);1265} else {1266RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_deinterleaved_slices[i] }));1267RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);1268}12691270RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_pong_slices[i] }));1271RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_pong_slices), 1);1272} else {1273if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {1274RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong_slices[i] }));1275RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);1276} else {1277RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_pong_slices[i] }));1278RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);1279}12801281RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_deinterleaved_slices[i] }));1282RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_slices), 1);1283}1284RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));12851286RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height, 1);1287}12881289RD::get_singleton()->compute_list_add_barrier(compute_list);1290}1291RD::get_singleton()->draw_command_end_label(); // Blur1292}12931294/* FOURTH PASS */1295// Interleave buffers1296// back to full size1297{1298RD::get_singleton()->draw_command_begin_label("Interleave Buffers");1299ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;1300ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;1301ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;1302ssao.interleave_push_constant.size_modifier = uint32_t(ssao_half_size ? 4 : 2);13031304shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);13051306int interleave_pipeline = SSAO_INTERLEAVE_HALF;1307if (ssao_quality == RS::ENV_SSAO_QUALITY_LOW) {1308interleave_pipeline = SSAO_INTERLEAVE;1309} else if (ssao_quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {1310interleave_pipeline = SSAO_INTERLEAVE_SMART;1311}13121313RID interleave_shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, interleave_pipeline - SSAO_INTERLEAVE);1314RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);13151316RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_final }));1317RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 0, u_upscale_buffer), 0);13181319if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) {1320RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved }));1321RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);1322} else {1323RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));1324RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);1325}13261327RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));13281329RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);1330RD::get_singleton()->compute_list_add_barrier(compute_list);1331RD::get_singleton()->draw_command_end_label(); // Interleave1332}1333RD::get_singleton()->draw_command_end_label(); //SSAO1334RD::get_singleton()->compute_list_end();13351336int zero[1] = { 0 };1337RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);1338}13391340/* Screen Space Reflection */13411342void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {1343ssr_roughness_quality = p_quality;1344}13451346void SSEffects::ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format) {1347if (p_ssr_buffers.roughness_quality != ssr_roughness_quality) {1348// Buffers will already be cleared if view count or viewport size has changed, also cleared them if we change roughness.1349p_render_buffers->clear_context(RB_SCOPE_SSR);1350}13511352Size2i internal_size = p_render_buffers->get_internal_size();1353p_ssr_buffers.size = Size2i(internal_size.x / 2, internal_size.y / 2);1354p_ssr_buffers.roughness_quality = ssr_roughness_quality;13551356// We are using barriers so we do not need to allocate textures for both views on anything but output...13571358p_render_buffers->create_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED, RD::DATA_FORMAT_R32_SFLOAT, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);1359p_render_buffers->create_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED, RD::DATA_FORMAT_R8G8B8A8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);13601361if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_render_buffers->has_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS)) {1362p_render_buffers->create_texture(RB_SCOPE_SSR, RB_BLUR_RADIUS, RD::DATA_FORMAT_R8_UNORM, RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 2); // 2 layers, for our two blur stages1363}13641365p_render_buffers->create_texture(RB_SCOPE_SSR, RB_INTERMEDIATE, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size, 1);1366p_render_buffers->create_texture(RB_SCOPE_SSR, RB_OUTPUT, p_color_format, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT, RD::TEXTURE_SAMPLES_1, p_ssr_buffers.size);1367}13681369void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const Projection *p_projections, const Vector3 *p_eye_offsets) {1370UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();1371ERR_FAIL_NULL(uniform_set_cache);1372MaterialStorage *material_storage = MaterialStorage::get_singleton();1373ERR_FAIL_NULL(material_storage);13741375uint32_t view_count = p_render_buffers->get_view_count();13761377RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);13781379{1380// Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders1381ScreenSpaceReflectionSceneData scene_data;13821383if (ssr.ubo.is_null()) {1384ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));1385}13861387for (uint32_t v = 0; v < view_count; v++) {1388store_camera(p_projections[v], scene_data.projection[v]);1389store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);1390scene_data.eye_offset[v][0] = p_eye_offsets[v].x;1391scene_data.eye_offset[v][1] = p_eye_offsets[v].y;1392scene_data.eye_offset[v][2] = p_eye_offsets[v].z;1393scene_data.eye_offset[v][3] = 0.0;1394}13951396RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data);1397}13981399uint32_t pipeline_specialization = 0;1400if (view_count > 1) {1401pipeline_specialization |= SSR_MULTIVIEW;1402}14031404RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();14051406for (uint32_t v = 0; v < view_count; v++) {1407// get buffers we need to use for this view1408RID diffuse_slice = p_render_buffers->get_internal_texture(v);1409RID depth_slice = p_render_buffers->get_depth_texture(v);1410RID depth_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_DEPTH_SCALED);1411RID normal_scaled = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_NORMAL_SCALED);1412RID intermediate = p_render_buffers->get_texture(RB_SCOPE_SSR, RB_INTERMEDIATE);1413RID output = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_OUTPUT, v, 0);14141415RID blur_radius[2];1416if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {1417blur_radius[0] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 0, 0);1418blur_radius[1] = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_BLUR_RADIUS, 1, 0);1419}14201421{1422char label[16];1423int len = snprintf(label, sizeof(label), "SSR View %d", v);1424RD::get_singleton()->draw_command_begin_label(Span<char>(label, len));1425}14261427{ //scale color and depth to half1428RD::get_singleton()->draw_command_begin_label("SSR Scale");14291430ScreenSpaceReflectionScalePushConstant push_constant;1431push_constant.view_index = v;1432push_constant.camera_z_far = p_projections[v].get_z_far();1433push_constant.camera_z_near = p_projections[v].get_z_near();1434push_constant.orthogonal = p_projections[v].is_orthogonal();1435push_constant.filter = false; // Enabling causes artifacts.1436push_constant.screen_size[0] = p_ssr_buffers.size.x;1437push_constant.screen_size[1] = p_ssr_buffers.size.y;14381439RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0);14401441RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]);14421443RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, diffuse_slice }));1444RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0);14451446RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_slice }));1447RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] }));1448RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1);14491450RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));1451RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);14521453RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled }));1454RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ normal_scaled }));1455RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3);14561457RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));1458RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);14591460RD::get_singleton()->compute_list_add_barrier(compute_list);14611462RD::get_singleton()->draw_command_end_label();1463}14641465{1466RD::get_singleton()->draw_command_begin_label("SSR main");14671468ScreenSpaceReflectionPushConstant push_constant;1469push_constant.view_index = v;1470push_constant.camera_z_far = p_projections[v].get_z_far();1471push_constant.camera_z_near = p_projections[v].get_z_near();1472push_constant.orthogonal = p_projections[v].is_orthogonal();1473push_constant.screen_size[0] = p_ssr_buffers.size.x;1474push_constant.screen_size[1] = p_ssr_buffers.size.y;1475push_constant.curve_fade_in = p_fade_in;1476push_constant.distance_fade = p_fade_out;1477push_constant.num_steps = p_max_steps;1478push_constant.depth_tolerance = p_tolerance;1479push_constant.use_half_res = true;1480push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]);1481push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]);1482push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];1483push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];14841485ScreenSpaceReflectionMode mode = (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;1486RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode);14871488RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]);14891490RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);1491RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);14921493// read from intermediate1494RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));1495RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ depth_scaled }));1496RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0);14971498if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {1499// write to output and blur radius1500RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));1501RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] }));1502RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output, u_blur_radius), 1);1503} else {1504// We are only writing output1505RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));1506RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output), 1);1507}15081509RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled }));1510RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2);15111512RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] }));1513RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3);15141515RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant));1516RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);15171518RD::get_singleton()->draw_command_end_label();1519}15201521if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {1522RD::get_singleton()->draw_command_begin_label("SSR filter");1523//blur15241525RD::get_singleton()->compute_list_add_barrier(compute_list);15261527ScreenSpaceReflectionFilterPushConstant push_constant;1528push_constant.view_index = v;1529push_constant.orthogonal = p_projections[v].is_orthogonal();1530push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));1531push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]);1532push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]);1533push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];1534push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];1535push_constant.vertical = 0;1536if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {1537push_constant.steps = p_max_steps / 3;1538push_constant.increment = 3;1539} else if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {1540push_constant.steps = p_max_steps / 2;1541push_constant.increment = 2;1542} else {1543push_constant.steps = p_max_steps;1544push_constant.increment = 1;1545}15461547push_constant.screen_size[0] = p_ssr_buffers.size.width;1548push_constant.screen_size[1] = p_ssr_buffers.size.height;15491550// Horizontal pass15511552SSRReflectionMode mode = SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL;15531554RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);15551556RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);15571558RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ output }));1559RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[0] }));1560RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_blur_radius), 0);15611562RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ normal_scaled }));1563RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);15641565RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));1566RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ blur_radius[1] }));1567RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate, u_blur_radius2), 2);15681569RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_scaled }));1570RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);15711572RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);1573RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);15741575RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));1576RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);1577RD::get_singleton()->compute_list_add_barrier(compute_list);15781579// Vertical pass15801581mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL;1582shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);15831584RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);15851586push_constant.vertical = 1;15871588RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius2), 0);1589RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);1590RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2);1591RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);1592RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);15931594RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));1595RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);15961597if (v != view_count - 1) {1598RD::get_singleton()->compute_list_add_barrier(compute_list);1599}16001601RD::get_singleton()->draw_command_end_label();1602}16031604RD::get_singleton()->draw_command_end_label();1605}16061607RD::get_singleton()->compute_list_end();1608}16091610/* Subsurface scattering */16111612void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) {1613sss_quality = p_quality;1614}16151616RS::SubSurfaceScatteringQuality SSEffects::sss_get_quality() const {1617return sss_quality;1618}16191620void SSEffects::sss_set_scale(float p_scale, float p_depth_scale) {1621sss_scale = p_scale;1622sss_depth_scale = p_depth_scale;1623}16241625void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size) {1626UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();1627ERR_FAIL_NULL(uniform_set_cache);1628MaterialStorage *material_storage = MaterialStorage::get_singleton();1629ERR_FAIL_NULL(material_storage);16301631RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);16321633// Our intermediate buffer is only created if we haven't created it already.1634RD::DataFormat format = p_render_buffers->get_base_data_format();1635uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;1636uint32_t layers = 1; // We only need one layer, we're handling one view at a time1637uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);1638RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);16391640Plane p = p_camera.xform4(Plane(1, 0, -1, 1));1641p.normal /= p.d;1642float unit_size = p.normal.x;16431644{ //scale color and depth to half1645RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();16461647sss.push_constant.camera_z_far = p_camera.get_z_far();1648sss.push_constant.camera_z_near = p_camera.get_z_near();1649sss.push_constant.orthogonal = p_camera.is_orthogonal();1650sss.push_constant.unit_size = unit_size;1651sss.push_constant.screen_size[0] = p_screen_size.x;1652sss.push_constant.screen_size[1] = p_screen_size.y;1653sss.push_constant.vertical = false;1654sss.push_constant.scale = sss_scale;1655sss.push_constant.depth_scale = sss_depth_scale;16561657RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1);1658RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1]);16591660RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));1661RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));1662RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));1663RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));1664RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));16651666// horizontal16671668RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);1669RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);1670RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);16711672RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));16731674RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);16751676RD::get_singleton()->compute_list_add_barrier(compute_list);16771678// vertical16791680RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);1681RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);1682RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);16831684sss.push_constant.vertical = true;1685RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));16861687RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);16881689RD::get_singleton()->compute_list_end();1690}1691}169216931694