Path: blob/master/servers/rendering/renderer_rd/effects/ss_effects.cpp
20912 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/effects/copy_effects.h"34#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"35#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"36#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"3738using namespace RendererRD;3940SSEffects *SSEffects::singleton = nullptr;4142static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {43for (int i = 0; i < 4; i++) {44for (int j = 0; j < 4; j++) {45p_array[i * 4 + j] = p_mtx.columns[i][j];46}47}48}4950SSEffects::SSEffects() {51singleton = this;5253// Initialize depth buffer for screen space effects54{55Vector<String> downsampler_modes;56downsampler_modes.push_back("\n");57downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");58downsampler_modes.push_back("\n#define GENERATE_MIPS\n");59downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");60downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");61downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");62downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");6364ss_effects.downsample_shader.initialize(downsampler_modes);6566ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();6768for (int i = 0; i < SS_EFFECTS_MAX; i++) {69ss_effects.pipelines[i].create_compute_pipeline(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));70}7172ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));73SSEffectsGatherConstants gather_constants;7475const int sub_pass_count = 5;76for (int pass = 0; pass < 4; pass++) {77for (int subPass = 0; subPass < sub_pass_count; subPass++) {78int a = pass;7980int spmap[5]{ 0, 1, 4, 3, 2 };81int b = spmap[subPass];8283float ca, sa;84float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math::PI * 0.5f;8586ca = Math::cos(angle0);87sa = Math::sin(angle0);8889float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;9091gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;92gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;93gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;94gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;95}96}9798RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);99}100101// Initialize Screen Space Indirect Lighting (SSIL)102ssil_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"));103104{105Vector<String> ssil_modes;106ssil_modes.push_back("\n");107ssil_modes.push_back("\n#define SSIL_BASE\n");108ssil_modes.push_back("\n#define ADAPTIVE\n");109110ssil.gather_shader.initialize(ssil_modes);111112ssil.gather_shader_version = ssil.gather_shader.version_create();113114for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {115ssil.pipelines[i].create_compute_pipeline(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));116}117ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));118}119120{121Vector<String> ssil_modes;122ssil_modes.push_back("\n#define GENERATE_MAP\n");123ssil_modes.push_back("\n#define PROCESS_MAPA\n");124ssil_modes.push_back("\n#define PROCESS_MAPB\n");125126ssil.importance_map_shader.initialize(ssil_modes);127128ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();129130for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {131ssil.pipelines[i].create_compute_pipeline(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));132}133ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));134int zero[1] = { 0 };135RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);136RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");137138Vector<RD::Uniform> uniforms;139{140RD::Uniform u;141u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;142u.binding = 0;143u.append_id(ssil.importance_map_load_counter);144uniforms.push_back(u);145}146ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);147RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");148}149150{151Vector<String> ssil_modes;152ssil_modes.push_back("\n#define MODE_NON_SMART\n");153ssil_modes.push_back("\n#define MODE_SMART\n");154ssil_modes.push_back("\n#define MODE_WIDE\n");155156ssil.blur_shader.initialize(ssil_modes);157158ssil.blur_shader_version = ssil.blur_shader.version_create();159for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {160ssil.pipelines[i].create_compute_pipeline(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));161}162}163164{165Vector<String> ssil_modes;166ssil_modes.push_back("\n#define MODE_NON_SMART\n");167ssil_modes.push_back("\n#define MODE_SMART\n");168ssil_modes.push_back("\n#define MODE_HALF\n");169170ssil.interleave_shader.initialize(ssil_modes);171172ssil.interleave_shader_version = ssil.interleave_shader.version_create();173for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {174ssil.pipelines[i].create_compute_pipeline(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));175}176}177178// Initialize Screen Space Ambient Occlusion (SSAO)179ssao_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"));180181{182RD::SamplerState sampler;183sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;184sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;185sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;186sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;187sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;188sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;189sampler.max_lod = 4;190191uint32_t pipeline = 0;192{193Vector<String> ssao_modes;194195ssao_modes.push_back("\n");196ssao_modes.push_back("\n#define SSAO_BASE\n");197ssao_modes.push_back("\n#define ADAPTIVE\n");198199ssao.gather_shader.initialize(ssao_modes);200201ssao.gather_shader_version = ssao.gather_shader.version_create();202203for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {204ssao.pipelines[pipeline].create_compute_pipeline(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));205pipeline++;206}207}208209{210Vector<String> ssao_modes;211ssao_modes.push_back("\n#define GENERATE_MAP\n");212ssao_modes.push_back("\n#define PROCESS_MAPA\n");213ssao_modes.push_back("\n#define PROCESS_MAPB\n");214215ssao.importance_map_shader.initialize(ssao_modes);216217ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();218219for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {220ssao.pipelines[pipeline].create_compute_pipeline(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));221222pipeline++;223}224225ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));226int zero[1] = { 0 };227RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);228RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");229230Vector<RD::Uniform> uniforms;231{232RD::Uniform u;233u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;234u.binding = 0;235u.append_id(ssao.importance_map_load_counter);236uniforms.push_back(u);237}238ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);239RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");240}241242{243Vector<String> ssao_modes;244ssao_modes.push_back("\n#define MODE_NON_SMART\n");245ssao_modes.push_back("\n#define MODE_SMART\n");246ssao_modes.push_back("\n#define MODE_WIDE\n");247248ssao.blur_shader.initialize(ssao_modes);249250ssao.blur_shader_version = ssao.blur_shader.version_create();251252for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {253ssao.pipelines[pipeline].create_compute_pipeline(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));254255pipeline++;256}257}258259{260Vector<String> ssao_modes;261ssao_modes.push_back("\n#define MODE_NON_SMART\n");262ssao_modes.push_back("\n#define MODE_SMART\n");263ssao_modes.push_back("\n#define MODE_HALF\n");264265ssao.interleave_shader.initialize(ssao_modes);266267ssao.interleave_shader_version = ssao.interleave_shader.version_create();268for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {269ssao.pipelines[pipeline].create_compute_pipeline(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));270pipeline++;271}272}273274ERR_FAIL_COND(pipeline != SSAO_MAX);275276ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);277}278279// Screen Space Reflections280ssr_half_size = GLOBAL_GET("rendering/environment/screen_space_reflection/half_size");281282{283{284Vector<String> ssr_downsample_modes;285ssr_downsample_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_DEFAULT286ssr_downsample_modes.push_back("\n#define MODE_ODD_WIDTH\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH287ssr_downsample_modes.push_back("\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_HEIGHT288ssr_downsample_modes.push_back("\n#define MODE_ODD_WIDTH\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH_AND_HEIGHT289290ssr.downsample_shader.initialize(ssr_downsample_modes);291ssr.downsample_shader_version = ssr.downsample_shader.version_create();292293for (uint32_t i = 0; i < SCREEN_SPACE_REFLECTION_DOWNSAMPLE_MAX; i++) {294ssr.downsample_pipelines[i].create_compute_pipeline(ssr.downsample_shader.version_get_shader(ssr.downsample_shader_version, i));295}296}297298{299Vector<String> ssr_hiz_modes;300ssr_hiz_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_HIZ_DEFAULT301ssr_hiz_modes.push_back("\n#define MODE_ODD_WIDTH\n"); // SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH302ssr_hiz_modes.push_back("\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_HIZ_ODD_HEIGHT303ssr_hiz_modes.push_back("\n#define MODE_ODD_WIDTH\n#define MODE_ODD_HEIGHT\n"); // SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH_AND_HEIGHT304305ssr.hiz_shader.initialize(ssr_hiz_modes);306ssr.hiz_shader_version = ssr.hiz_shader.version_create();307308for (uint32_t i = 0; i < SCREEN_SPACE_REFLECTION_HIZ_MAX; i++) {309ssr.hiz_pipelines[i].create_compute_pipeline(ssr.hiz_shader.version_get_shader(ssr.hiz_shader_version, i));310}311}312313{314Vector<String> ssr_modes;315ssr_modes.push_back("\n");316317ssr.ssr_shader.initialize(ssr_modes);318ssr.ssr_shader_version = ssr.ssr_shader.version_create();319320ssr.ssr_pipeline.create_compute_pipeline(ssr.ssr_shader.version_get_shader(ssr.ssr_shader_version, 0));321}322323{324Vector<String> ssr_filter_modes;325ssr_filter_modes.push_back("\n");326327ssr.filter_shader.initialize(ssr_filter_modes);328ssr.filter_shader_version = ssr.filter_shader.version_create();329330ssr.filter_pipeline.create_compute_pipeline(ssr.filter_shader.version_get_shader(ssr.filter_shader_version, 0));331}332333{334Vector<String> ssr_resolve_modes;335ssr_resolve_modes.push_back("\n");336337ssr.resolve_shader.initialize(ssr_resolve_modes);338ssr.resolve_shader_version = ssr.resolve_shader.version_create();339340ssr.resolve_pipeline.create_compute_pipeline(ssr.resolve_shader.version_get_shader(ssr.resolve_shader_version, 0));341}342}343344// Subsurface scattering345sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));346sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");347sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");348349{350Vector<String> sss_modes;351sss_modes.push_back("\n#define USE_11_SAMPLES\n");352sss_modes.push_back("\n#define USE_17_SAMPLES\n");353sss_modes.push_back("\n#define USE_25_SAMPLES\n");354355sss.shader.initialize(sss_modes);356357sss.shader_version = sss.shader.version_create();358359for (int i = 0; i < SUBSURFACE_SCATTERING_MODE_MAX; i++) {360sss.pipelines[i].create_compute_pipeline(sss.shader.version_get_shader(sss.shader_version, i));361}362}363}364365void SSEffects::allocate_last_frame_buffer(Ref<RenderSceneBuffersRD> p_render_buffers, bool p_use_ssil, bool p_use_ssr) {366Size2i last_frame_size = p_render_buffers->get_internal_size();367uint32_t mipmaps = 1;368uint32_t view_count = p_render_buffers->get_view_count();369370if (!p_use_ssil && p_use_ssr && ssr_half_size) {371last_frame_size /= 2;372}373374if (p_use_ssil) {375mipmaps = 6;376}377378bool should_create = true;379bool has_texture = p_render_buffers->has_texture(RB_SCOPE_SSLF, RB_LAST_FRAME);380381if (has_texture) {382RID last_frame_texture = p_render_buffers->get_texture(RB_SCOPE_SSLF, RB_LAST_FRAME);383RD::TextureFormat texture_format = RD::get_singleton()->texture_get_format(last_frame_texture);384should_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;385}386387if (should_create) {388if (has_texture) {389p_render_buffers->clear_context(RB_SCOPE_SSLF);390}391392RID 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);393RD::get_singleton()->texture_clear(last_frame_texture, Color(0, 0, 0, 0), 0, mipmaps, 0, view_count);394}395}396397void SSEffects::copy_internal_texture_to_last_frame(Ref<RenderSceneBuffersRD> p_render_buffers, CopyEffects &p_copy_effects) {398uint32_t mipmaps = p_render_buffers->get_texture_format(RB_SCOPE_SSLF, RB_LAST_FRAME).mipmaps;399for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {400for (uint32_t m = 0; m < mipmaps; m++) {401RID source;402if (m == 0) {403source = p_render_buffers->get_internal_texture(v);404} else {405source = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, m - 1);406}407408RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, m);409410Size2i source_size = RD::get_singleton()->texture_size(source);411Size2i dest_size = RD::get_singleton()->texture_size(dest);412413if (m == 0 && source_size == dest_size) {414p_copy_effects.copy_to_rect(source, dest, Rect2i(Vector2i(), source_size), false, false, false, false, false, true);415} else {416p_copy_effects.make_mipmap(source, dest, dest_size);417}418}419}420}421422SSEffects::~SSEffects() {423{424// Cleanup SS Reflections425for (int i = 0; i < SCREEN_SPACE_REFLECTION_DOWNSAMPLE_MAX; i++) {426ssr.downsample_pipelines[i].free();427}428for (int i = 0; i < SCREEN_SPACE_REFLECTION_HIZ_MAX; i++) {429ssr.hiz_pipelines[i].free();430}431ssr.ssr_pipeline.free();432ssr.filter_pipeline.free();433ssr.resolve_pipeline.free();434435ssr.downsample_shader.version_free(ssr.downsample_shader_version);436ssr.hiz_shader.version_free(ssr.hiz_shader_version);437ssr.ssr_shader.version_free(ssr.ssr_shader_version);438ssr.filter_shader.version_free(ssr.filter_shader_version);439ssr.resolve_shader.version_free(ssr.resolve_shader_version);440441if (ssr.ubo.is_valid()) {442RD::get_singleton()->free_rid(ssr.ubo);443}444}445446{447// Cleanup SS downsampler448for (int i = 0; i < SS_EFFECTS_MAX; i++) {449ss_effects.pipelines[i].free();450}451452ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);453454RD::get_singleton()->free_rid(ss_effects.mirror_sampler);455RD::get_singleton()->free_rid(ss_effects.gather_constants_buffer);456}457458{459// Cleanup SSIL460for (int i = 0; i < SSIL_MAX; i++) {461ssil.pipelines[i].free();462}463464ssil.blur_shader.version_free(ssil.blur_shader_version);465ssil.gather_shader.version_free(ssil.gather_shader_version);466ssil.interleave_shader.version_free(ssil.interleave_shader_version);467ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);468469RD::get_singleton()->free_rid(ssil.importance_map_load_counter);470RD::get_singleton()->free_rid(ssil.projection_uniform_buffer);471}472473{474// Cleanup SSAO475for (int i = 0; i < SSAO_MAX; i++) {476ssao.pipelines[i].free();477}478479ssao.blur_shader.version_free(ssao.blur_shader_version);480ssao.gather_shader.version_free(ssao.gather_shader_version);481ssao.interleave_shader.version_free(ssao.interleave_shader_version);482ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);483484RD::get_singleton()->free_rid(ssao.importance_map_load_counter);485}486487{488// Cleanup Subsurface scattering489for (int i = 0; i < SUBSURFACE_SCATTERING_MODE_MAX; i++) {490sss.pipelines[i].free();491}492493sss.shader.version_free(sss.shader_version);494}495496singleton = nullptr;497}498499/* SS Downsampler */500501void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_view, const Projection &p_projection) {502UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();503ERR_FAIL_NULL(uniform_set_cache);504MaterialStorage *material_storage = MaterialStorage::get_singleton();505ERR_FAIL_NULL(material_storage);506507uint32_t view_count = p_render_buffers->get_view_count();508Size2i full_screen_size = p_render_buffers->get_internal_size();509Size2i size((full_screen_size.x + 1) / 2, (full_screen_size.y + 1) / 2);510511// Make sure our buffers exist, buffers are automatically cleared if view count or size changes.512if (!p_render_buffers->has_texture(RB_SCOPE_SSDS, RB_LINEAR_DEPTH)) {513p_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);514}515516// Downsample and deinterleave the depth buffer for SSAO and SSIL517RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();518519int downsample_mode = SS_EFFECTS_DOWNSAMPLE;520bool use_mips = ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;521522if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {523downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;524} else if (use_mips) {525downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;526}527528bool use_half_size = false;529bool use_full_mips = false;530531if (ssao_half_size && ssil_half_size) {532downsample_mode++;533use_half_size = true;534} else if (ssao_half_size != ssil_half_size) {535if (use_mips) {536downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;537use_full_mips = true;538} else {539// Only need the first two mipmaps, but the cost to generate the next two is trivial540// TODO investigate the benefit of a shader version to generate only 2 mips541downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;542use_mips = true;543}544}545546RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);547int depth_index = use_half_size ? 1 : 0;548549RD::get_singleton()->draw_command_begin_label("Downsample Depth");550551RID downsample_uniform_set;552if (use_mips) {553// Grab our downsample uniform set from cache, these are automatically cleaned up if the depth textures are cleared.554// This also ensures we can switch between left eye and right eye uniform sets without recreating the uniform twice a frame.555thread_local LocalVector<RD::Uniform> u_depths;556u_depths.clear();557558// Note, use_full_mips is true if either SSAO or SSIL uses half size, but the other full size and we're using mips.559// That means we're filling all 5 levels.560// In this scenario `depth_index` will be 0.561for (int i = 0; i < (use_full_mips ? 4 : 3); i++) {562RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index + i + 1, 4, 1);563564RD::Uniform u_depth;565u_depth.uniform_type = RD::UNIFORM_TYPE_IMAGE;566u_depth.binding = i;567u_depth.append_id(depth_mipmap);568u_depths.push_back(u_depth);569}570571// This before only used SS_EFFECTS_DOWNSAMPLE_MIPMAP or SS_EFFECTS_DOWNSAMPLE_FULL_MIPS572downsample_uniform_set = uniform_set_cache->get_cache_vec(shader, 2, u_depths);573}574575Projection correction;576correction.set_depth_correction(false);577Projection temp = correction * p_projection;578579float depth_linearize_mul = -temp.columns[3][2];580float depth_linearize_add = temp.columns[2][2];581if (depth_linearize_mul * depth_linearize_add < 0) {582depth_linearize_add = -depth_linearize_add;583}584585ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();586ss_effects.downsample_push_constant.z_near = depth_linearize_mul;587ss_effects.downsample_push_constant.z_far = depth_linearize_add;588if (ss_effects.downsample_push_constant.orthogonal) {589ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();590ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();591}592ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / full_screen_size.x;593ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / full_screen_size.y;594ss_effects.downsample_push_constant.radius_sq = 1.0;595596RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);597598RID depth_texture = p_render_buffers->get_depth_texture(p_view);599RID depth_mipmap = p_render_buffers->get_texture_slice(RB_SCOPE_SSDS, RB_LINEAR_DEPTH, p_view * 4, depth_index, 4, 1);600601RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth_texture }));602RD::Uniform u_depth_mipmap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ depth_mipmap }));603604RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode].get_rid());605RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);606RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmap), 1);607if (use_mips) {608RD::get_singleton()->compute_list_bind_uniform_set(compute_list, downsample_uniform_set, 2);609}610RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));611612if (use_half_size) {613size = Size2i(size.x >> 1, size.y >> 1).maxi(1);614}615616RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);617RD::get_singleton()->compute_list_add_barrier(compute_list);618RD::get_singleton()->draw_command_end_label();619620RD::get_singleton()->compute_list_end();621622ss_effects.used_full_mips_last_frame = use_full_mips;623ss_effects.used_half_size_last_frame = use_half_size;624ss_effects.used_mips_last_frame = use_mips;625}626627/* SSIL */628629void 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) {630ssil_quality = p_quality;631ssil_half_size = p_half_size;632ssil_adaptive_target = p_adaptive_target;633ssil_blur_passes = p_blur_passes;634ssil_fadeout_from = p_fadeout_from;635ssil_fadeout_to = p_fadeout_to;636}637638void 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) {639UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();640ERR_FAIL_NULL(uniform_set_cache);641642RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);643if ((ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {644RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);645}646RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);647648RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);649650for (int i = 0; i < 4; i++) {651if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {652continue;653}654655RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] }));656RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] }));657658ssil.gather_push_constant.pass_coord_offset[0] = i % 2;659ssil.gather_push_constant.pass_coord_offset[1] = i / 2;660ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;661ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;662ssil.gather_push_constant.pass = i;663RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2);664RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));665666Size2i size;667// Calculate size same way as we created the buffer668if (ssil_half_size) {669size.x = (p_settings.full_screen_size.x + 3) / 4;670size.y = (p_settings.full_screen_size.y + 3) / 4;671} else {672size.x = (p_settings.full_screen_size.x + 1) / 2;673size.y = (p_settings.full_screen_size.y + 1) / 2;674}675676RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);677}678RD::get_singleton()->compute_list_add_barrier(p_compute_list);679}680681void SSEffects::ssil_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings) {682if (p_ssil_buffers.half_size != ssil_half_size) {683p_render_buffers->clear_context(RB_SCOPE_SSIL);684}685686p_ssil_buffers.half_size = ssil_half_size;687if (p_ssil_buffers.half_size) {688p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;689p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;690p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;691p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;692} else {693p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;694p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;695p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;696p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;697}698699uint32_t view_count = p_render_buffers->get_view_count();700Size2i full_size = Size2i(p_ssil_buffers.buffer_width, p_ssil_buffers.buffer_height);701Size2i half_size = Size2i(p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height);702703// We create our intermediate and final results as render buffers.704// These are automatically cached and cleaned up when our viewport resizes705// or when our viewport gets destroyed.706707if (!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...708RID 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);709RD::get_singleton()->texture_clear(final, Color(0, 0, 0, 0), 0, 1, 0, view_count);710}711712// As we're not clearing these, and render buffers will return the cached texture if it already exists,713// we don't first check has_texture here714715p_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);716p_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);717p_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);718p_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);719p_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);720}721722void 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) {723UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();724ERR_FAIL_NULL(uniform_set_cache);725MaterialStorage *material_storage = MaterialStorage::get_singleton();726ERR_FAIL_NULL(material_storage);727728RD::get_singleton()->draw_command_begin_label("Process Screen-Space Indirect Lighting");729730// Obtain our (cached) buffer slices for the view we are rendering.731RID last_frame = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, p_view, 0, 1, 6);732RID deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);733RID deinterleaved_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, 4 * p_view, 0, 4, 1);734RID edges = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, 4 * p_view, 0, 4, 1);735RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_MAP, p_view, 0);736RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_IMPORTANCE_PONG, p_view, 0);737738RID deinterleaved_slices[4];739RID deinterleaved_pong_slices[4];740RID edges_slices[4];741for (uint32_t i = 0; i < 4; i++) {742deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED, p_view * 4 + i, 0);743deinterleaved_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);744edges_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_EDGES, p_view * 4 + i, 0);745}746747//Store projection info before starting the compute list748SSILProjectionUniforms projection_uniforms;749store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);750751RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);752753memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));754755RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER);756RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);757RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);758759RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();760{761RD::get_singleton()->draw_command_begin_label("Gather Samples");762ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;763ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;764765ssil.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;766ssil.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;767if (ssil_half_size) {768ssil.gather_push_constant.half_screen_pixel_size[0] *= 2.0;769ssil.gather_push_constant.half_screen_pixel_size[1] *= 2.0;770}771ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.75;772ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.75;773float tan_half_fov_x = 1.0 / p_projection.columns[0][0];774float tan_half_fov_y = 1.0 / p_projection.columns[1][1];775ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;776ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;777ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;778ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;779ssil.gather_push_constant.z_near = p_projection.get_z_near();780ssil.gather_push_constant.z_far = p_projection.get_z_far();781ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();782783ssil.gather_push_constant.radius = p_settings.radius;784float radius_near_limit = (p_settings.radius * 1.2f);785if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {786radius_near_limit *= 1.50f;787788if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {789ssil.gather_push_constant.radius *= 0.8f;790}791}792radius_near_limit /= tan_half_fov_y;793ssil.gather_push_constant.intensity = p_settings.intensity * Math::PI;794ssil.gather_push_constant.fade_out_mul = -1.0 / (ssil_fadeout_to - ssil_fadeout_from);795ssil.gather_push_constant.fade_out_add = ssil_fadeout_from / (ssil_fadeout_to - ssil_fadeout_from) + 1.0;796ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;797ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;798ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;799800ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);801ssil.gather_push_constant.adaptive_sample_limit = ssil_adaptive_target;802803ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1);804ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1;805806// We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.807// It also ensures that we're reusing the right cached entry in a multiview situation without us having to808// remember each instance of the uniform set.809810RID projection_uniform_set;811{812RD::Uniform u_last_frame;813u_last_frame.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;814u_last_frame.binding = 0;815u_last_frame.append_id(default_mipmap_sampler);816u_last_frame.append_id(last_frame);817818RD::Uniform u_projection;819u_projection.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;820u_projection.binding = 1;821u_projection.append_id(ssil.projection_uniform_buffer);822823projection_uniform_set = uniform_set_cache->get_cache(shader, 3, u_last_frame, u_projection);824}825826RID gather_uniform_set;827{828RID 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);829830RD::Uniform u_depth_texture_view;831u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;832u_depth_texture_view.binding = 0;833u_depth_texture_view.append_id(ss_effects.mirror_sampler);834u_depth_texture_view.append_id(depth_texture_view);835836RD::Uniform u_normal_buffer;837u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;838u_normal_buffer.binding = 1;839u_normal_buffer.append_id(p_normal_buffer);840841RD::Uniform u_gather_constants_buffer;842u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;843u_gather_constants_buffer.binding = 2;844u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);845846gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);847}848849RID importance_map_uniform_set;850{851RD::Uniform u_pong;852u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;853u_pong.binding = 0;854u_pong.append_id(deinterleaved_pong);855856RD::Uniform u_importance_map;857u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;858u_importance_map.binding = 1;859u_importance_map.append_id(default_sampler);860u_importance_map.append_id(importance_map);861862RD::Uniform u_load_counter;863u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;864u_load_counter.binding = 2;865u_load_counter.append_id(ssil.importance_map_load_counter);866867RID shader_adaptive = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, SSIL_GATHER_ADAPTIVE);868importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);869}870871if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) {872RD::get_singleton()->draw_command_begin_label("Generate Importance Map");873ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;874ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;875ssil.importance_map_push_constant.intensity = p_settings.intensity * Math::PI;876877//base pass878RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE].get_rid());879gather_ssil(compute_list, deinterleaved_pong_slices, edges_slices, p_settings, true, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);880881//generate importance map882RID gen_imp_shader = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 0);883RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));884RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));885886RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP].get_rid());887RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ssil_pong_with_sampler), 0);888RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);889RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));890RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);891RD::get_singleton()->compute_list_add_barrier(compute_list);892893// process Importance Map A894RID proc_imp_shader_a = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 1);895RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));896RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));897898RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA].get_rid());899RD::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);900RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);901RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));902RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);903RD::get_singleton()->compute_list_add_barrier(compute_list);904905// process Importance Map B906RID proc_imp_shader_b = ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2);907RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));908909RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB].get_rid());910RD::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);911RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);912RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);913RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));914RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);915RD::get_singleton()->compute_list_add_barrier(compute_list);916917RD::get_singleton()->draw_command_end_label(); // Importance Map918919RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE].get_rid());920} else {921RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER].get_rid());922}923924gather_ssil(compute_list, deinterleaved_slices, edges_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set, projection_uniform_set);925RD::get_singleton()->draw_command_end_label(); //Gather926}927928{929RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");930ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;931ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;932ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;933934int blur_passes = ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? ssil_blur_passes : 1;935936shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);937938for (int pass = 0; pass < blur_passes; pass++) {939int blur_pipeline = SSIL_BLUR_PASS;940if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {941blur_pipeline = SSIL_BLUR_PASS_SMART;942if (pass < blur_passes - 2) {943blur_pipeline = SSIL_BLUR_PASS_WIDE;944}945}946947RID blur_shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, blur_pipeline - SSIL_BLUR_PASS);948949for (int i = 0; i < 4; i++) {950if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {951continue;952}953954RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline].get_rid());955if (pass % 2 == 0) {956if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {957RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_slices[i] }));958RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);959} else {960RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_slices[i] }));961RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_slice), 0);962}963964RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_pong_slices[i] }));965RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_pong_slice), 1);966} else {967if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {968RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong_slices[i] }));969RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);970} else {971RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, deinterleaved_pong_slices[i] }));972RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ssil_pong_slice), 0);973}974975RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ deinterleaved_slices[i] }));976RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ssil_slice), 1);977}978979RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges_slices[i] }));980RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 2, u_edges_slice), 2);981982RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));983984// Use the size of the actual buffer we're processing here or we won't cover the entire image.985int x_groups = p_ssil_buffers.buffer_width;986int y_groups = p_ssil_buffers.buffer_height;987988RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);989}990991RD::get_singleton()->compute_list_add_barrier(compute_list);992}993994RD::get_singleton()->draw_command_end_label(); // Blur995}996997{998RD::get_singleton()->draw_command_begin_label("Interleave Buffers");999ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;1000ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;1001ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;1002ssil.interleave_push_constant.size_modifier = uint32_t(ssil_half_size ? 4 : 2);10031004int interleave_pipeline = SSIL_INTERLEAVE_HALF;1005if (ssil_quality == RS::ENV_SSIL_QUALITY_LOW) {1006interleave_pipeline = SSIL_INTERLEAVE;1007} else if (ssil_quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {1008interleave_pipeline = SSIL_INTERLEAVE_SMART;1009}10101011shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);10121013RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline].get_rid());10141015RID final = p_render_buffers->get_texture_slice(RB_SCOPE_SSIL, RB_FINAL, p_view, 0);1016RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ final }));1017RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);10181019if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) {1020RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved }));1021RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);1022} else {1023RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, deinterleaved_pong }));1024RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);1025}10261027RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ edges }));1028RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);10291030RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));10311032RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);1033RD::get_singleton()->compute_list_add_barrier(compute_list);1034RD::get_singleton()->draw_command_end_label(); // Interleave1035}10361037RD::get_singleton()->draw_command_end_label(); // SSIL10381039RD::get_singleton()->compute_list_end();10401041int zero[1] = { 0 };1042RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);1043}10441045/* SSAO */10461047void 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) {1048ssao_quality = p_quality;1049ssao_half_size = p_half_size;1050ssao_adaptive_target = p_adaptive_target;1051ssao_blur_passes = p_blur_passes;1052ssao_fadeout_from = p_fadeout_from;1053ssao_fadeout_to = p_fadeout_to;1054}10551056void 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) {1057UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();1058ERR_FAIL_NULL(uniform_set_cache);10591060RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);1061if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {1062RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);1063}10641065RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //10661067for (int i = 0; i < 4; i++) {1068if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {1069continue;1070}10711072RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, p_ao_slices[i]);10731074ssao.gather_push_constant.pass_coord_offset[0] = i % 2;1075ssao.gather_push_constant.pass_coord_offset[1] = i / 2;1076ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;1077ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;1078ssao.gather_push_constant.pass = i;1079RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);1080RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));10811082Size2i size;1083// Make sure we use the same size as with which our buffer was created1084if (ssao_half_size) {1085size.x = (p_settings.full_screen_size.x + 3) / 4;1086size.y = (p_settings.full_screen_size.y + 3) / 4;1087} else {1088size.x = (p_settings.full_screen_size.x + 1) / 2;1089size.y = (p_settings.full_screen_size.y + 1) / 2;1090}10911092RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);1093}1094RD::get_singleton()->compute_list_add_barrier(p_compute_list);1095}10961097void SSEffects::ssao_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings) {1098if (p_ssao_buffers.half_size != ssao_half_size) {1099p_render_buffers->clear_context(RB_SCOPE_SSAO);1100}11011102p_ssao_buffers.half_size = ssao_half_size;1103if (ssao_half_size) {1104p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;1105p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;1106p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;1107p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;1108} else {1109p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;1110p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;1111p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;1112p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;1113}11141115uint32_t view_count = p_render_buffers->get_view_count();1116Size2i full_size = Size2i(p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height);1117Size2i half_size = Size2i(p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height);11181119// As we're not clearing these, and render buffers will return the cached texture if it already exists,1120// we don't first check has_texture here11211122p_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);1123p_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);1124p_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);1125p_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);1126p_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);1127}11281129void 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) {1130UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();1131ERR_FAIL_NULL(uniform_set_cache);1132MaterialStorage *material_storage = MaterialStorage::get_singleton();1133ERR_FAIL_NULL(material_storage);11341135// Obtain our (cached) buffer slices for the view we are rendering.1136RID ao_deinterleaved = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4, 0, 4, 1);1137RID ao_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4, 0, 4, 1);1138RID importance_map = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_MAP, p_view, 0);1139RID importance_pong = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_IMPORTANCE_PONG, p_view, 0);1140RID ao_final = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_FINAL, p_view, 0);11411142RID ao_deinterleaved_slices[4];1143RID ao_pong_slices[4];1144for (uint32_t i = 0; i < 4; i++) {1145ao_deinterleaved_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED, p_view * 4 + i, 0);1146ao_pong_slices[i] = p_render_buffers->get_texture_slice(RB_SCOPE_SSAO, RB_DEINTERLEAVED_PONG, p_view * 4 + i, 0);1147}11481149RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();1150memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));1151/* FIRST PASS */11521153RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER);1154RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);11551156RD::get_singleton()->draw_command_begin_label("Process Screen-Space Ambient Occlusion");1157/* SECOND PASS */1158// Sample SSAO1159{1160RD::get_singleton()->draw_command_begin_label("Gather Samples");1161ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;1162ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;11631164ssao.gather_push_constant.half_screen_pixel_size[0] = 2.0 / p_settings.full_screen_size.x;1165ssao.gather_push_constant.half_screen_pixel_size[1] = 2.0 / p_settings.full_screen_size.y;1166if (ssao_half_size) {1167ssao.gather_push_constant.half_screen_pixel_size[0] *= 2.0;1168ssao.gather_push_constant.half_screen_pixel_size[1] *= 2.0;1169}1170ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.75;1171ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.75;1172float tan_half_fov_x = 1.0 / p_projection.columns[0][0];1173float tan_half_fov_y = 1.0 / p_projection.columns[1][1];1174ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;1175ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;1176ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;1177ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;1178ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();11791180ssao.gather_push_constant.radius = p_settings.radius;1181float radius_near_limit = (p_settings.radius * 1.2f);1182if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {1183radius_near_limit *= 1.50f;11841185if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {1186ssao.gather_push_constant.radius *= 0.8f;1187}1188}1189radius_near_limit /= tan_half_fov_y;1190ssao.gather_push_constant.intensity = p_settings.intensity;1191ssao.gather_push_constant.shadow_power = p_settings.power;1192ssao.gather_push_constant.shadow_clamp = 0.98;1193ssao.gather_push_constant.fade_out_mul = -1.0 / (ssao_fadeout_to - ssao_fadeout_from);1194ssao.gather_push_constant.fade_out_add = ssao_fadeout_from / (ssao_fadeout_to - ssao_fadeout_from) + 1.0;1195ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;1196ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;1197ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;11981199ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);1200ssao.gather_push_constant.adaptive_sample_limit = ssao_adaptive_target;12011202ssao.gather_push_constant.detail_intensity = p_settings.detail;1203ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1);1204ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1;12051206// We are using our uniform cache so our uniform sets are automatically freed when our textures are freed.1207// It also ensures that we're reusing the right cached entry in a multiview situation without us having to1208// remember each instance of the uniform set.1209RID gather_uniform_set;1210{1211RID 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);12121213RD::Uniform u_depth_texture_view;1214u_depth_texture_view.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;1215u_depth_texture_view.binding = 0;1216u_depth_texture_view.append_id(ss_effects.mirror_sampler);1217u_depth_texture_view.append_id(depth_texture_view);12181219RD::Uniform u_normal_buffer;1220u_normal_buffer.uniform_type = RD::UNIFORM_TYPE_IMAGE;1221u_normal_buffer.binding = 1;1222u_normal_buffer.append_id(p_normal_buffer);12231224RD::Uniform u_gather_constants_buffer;1225u_gather_constants_buffer.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;1226u_gather_constants_buffer.binding = 2;1227u_gather_constants_buffer.append_id(ss_effects.gather_constants_buffer);12281229gather_uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth_texture_view, u_normal_buffer, u_gather_constants_buffer);1230}12311232RID importance_map_uniform_set;1233{1234RD::Uniform u_pong;1235u_pong.uniform_type = RD::UNIFORM_TYPE_IMAGE;1236u_pong.binding = 0;1237u_pong.append_id(ao_pong);12381239RD::Uniform u_importance_map;1240u_importance_map.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;1241u_importance_map.binding = 1;1242u_importance_map.append_id(default_sampler);1243u_importance_map.append_id(importance_map);12441245RD::Uniform u_load_counter;1246u_load_counter.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1247u_load_counter.binding = 2;1248u_load_counter.append_id(ssao.importance_map_load_counter);12491250RID shader_adaptive = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, SSAO_GATHER_ADAPTIVE);1251importance_map_uniform_set = uniform_set_cache->get_cache(shader_adaptive, 1, u_pong, u_importance_map, u_load_counter);1252}12531254if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) {1255RD::get_singleton()->draw_command_begin_label("Generate Importance Map");1256ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;1257ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;1258ssao.importance_map_push_constant.intensity = p_settings.intensity;1259ssao.importance_map_push_constant.power = p_settings.power;12601261//base pass1262RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE].get_rid());1263gather_ssao(compute_list, ao_pong_slices, p_settings, true, gather_uniform_set, RID());12641265//generate importance map1266RID gen_imp_shader = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 0);1267RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP].get_rid());12681269RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));1270RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 0, u_ao_pong_with_sampler), 0);12711272RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_map }));1273RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(gen_imp_shader, 1, u_importance_map), 1);12741275RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));1276RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);1277RD::get_singleton()->compute_list_add_barrier(compute_list);12781279//process importance map A1280RID proc_imp_shader_a = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 1);1281RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA].get_rid());12821283RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_map }));1284RD::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);12851286RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ importance_pong }));1287RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_a, 1, u_importance_map_pong), 1);12881289RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));1290RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);1291RD::get_singleton()->compute_list_add_barrier(compute_list);12921293//process Importance Map B1294RID proc_imp_shader_b = ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2);1295RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB].get_rid());12961297RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, importance_pong }));1298RD::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);12991300RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(proc_imp_shader_b, 1, u_importance_map), 1);1301RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);1302RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));1303RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);1304RD::get_singleton()->compute_list_add_barrier(compute_list);13051306RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE].get_rid());1307RD::get_singleton()->draw_command_end_label(); // Importance Map1308} else {1309RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER].get_rid());1310}13111312gather_ssao(compute_list, ao_deinterleaved_slices, p_settings, false, gather_uniform_set, importance_map_uniform_set);1313RD::get_singleton()->draw_command_end_label(); // Gather SSAO1314}13151316// /* THIRD PASS */1317// // Blur1318//1319{1320RD::get_singleton()->draw_command_begin_label("Edge-Aware Blur");1321ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;1322ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;1323ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;13241325int blur_passes = ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? ssao_blur_passes : 1;13261327shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);13281329for (int pass = 0; pass < blur_passes; pass++) {1330int blur_pipeline = SSAO_BLUR_PASS;1331if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {1332if (pass < blur_passes - 2) {1333blur_pipeline = SSAO_BLUR_PASS_WIDE;1334} else {1335blur_pipeline = SSAO_BLUR_PASS_SMART;1336}1337}13381339for (int i = 0; i < 4; i++) {1340if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {1341continue;1342}13431344RID blur_shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, blur_pipeline - SSAO_BLUR_PASS);1345RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline].get_rid());1346if (pass % 2 == 0) {1347if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {1348RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved_slices[i] }));1349RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);1350} else {1351RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_deinterleaved_slices[i] }));1352RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_slices_with_sampler), 0);1353}13541355RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_pong_slices[i] }));1356RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_pong_slices), 1);1357} else {1358if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {1359RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong_slices[i] }));1360RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);1361} else {1362RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, ao_pong_slices[i] }));1363RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 0, u_ao_pong_slices_with_sampler), 0);1364}13651366RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_deinterleaved_slices[i] }));1367RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(blur_shader, 1, u_ao_slices), 1);1368}1369RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));13701371RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.buffer_width, p_ssao_buffers.buffer_height, 1);1372}13731374RD::get_singleton()->compute_list_add_barrier(compute_list);1375}1376RD::get_singleton()->draw_command_end_label(); // Blur1377}13781379/* FOURTH PASS */1380// Interleave buffers1381// back to full size1382{1383RD::get_singleton()->draw_command_begin_label("Interleave Buffers");1384ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;1385ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;1386ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;1387ssao.interleave_push_constant.size_modifier = uint32_t(ssao_half_size ? 4 : 2);13881389shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);13901391int interleave_pipeline = SSAO_INTERLEAVE_HALF;1392if (ssao_quality == RS::ENV_SSAO_QUALITY_LOW) {1393interleave_pipeline = SSAO_INTERLEAVE;1394} else if (ssao_quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {1395interleave_pipeline = SSAO_INTERLEAVE_SMART;1396}13971398RID interleave_shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, interleave_pipeline - SSAO_INTERLEAVE);1399RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline].get_rid());14001401RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ ao_final }));1402RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 0, u_upscale_buffer), 0);14031404if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) {1405RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_deinterleaved }));1406RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);1407} else {1408RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, ao_pong }));1409RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(interleave_shader, 1, u_ao), 1);1410}14111412RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));14131414RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);1415RD::get_singleton()->compute_list_add_barrier(compute_list);1416RD::get_singleton()->draw_command_end_label(); // Interleave1417}1418RD::get_singleton()->draw_command_end_label(); //SSAO1419RD::get_singleton()->compute_list_end();14201421int zero[1] = { 0 };1422RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);1423}14241425/* Screen Space Reflection */14261427void SSEffects::ssr_set_half_size(bool p_half_size) {1428ssr_half_size = p_half_size;1429}14301431void SSEffects::ssr_allocate_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, SSRRenderBuffers &p_ssr_buffers, const RD::DataFormat p_color_format) {1432if (p_ssr_buffers.half_size != ssr_half_size) {1433p_render_buffers->clear_context(RB_SCOPE_SSR);1434}14351436Vector2i internal_size = p_render_buffers->get_internal_size();1437p_ssr_buffers.size = ssr_half_size ? (internal_size / 2) : internal_size;14381439uint32_t cur_width = p_ssr_buffers.size.width;1440uint32_t cur_height = p_ssr_buffers.size.height;1441p_ssr_buffers.mipmaps = 1;14421443while (cur_width > 1 && cur_height > 1) {1444if (cur_width > 1) {1445cur_width /= 2;1446}1447if (cur_height > 1) {1448cur_height /= 2;1449}1450++p_ssr_buffers.mipmaps;1451}14521453p_ssr_buffers.half_size = ssr_half_size;14541455uint32_t view_count = p_render_buffers->get_view_count();14561457if (ssr_half_size) {1458p_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);1459}14601461p_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);1462p_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);1463p_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);14641465if (ssr_half_size) {1466p_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);1467}1468}14691470void 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) {1471UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();1472ERR_FAIL_NULL(uniform_set_cache);1473MaterialStorage *material_storage = MaterialStorage::get_singleton();1474ERR_FAIL_NULL(material_storage);14751476uint32_t view_count = p_render_buffers->get_view_count();1477{1478// Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders1479ScreenSpaceReflectionSceneData scene_data;14801481if (ssr.ubo.is_null()) {1482ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));1483}14841485Projection correction;1486correction.set_depth_correction(true);14871488for (uint32_t v = 0; v < view_count; v++) {1489Projection projection = correction * p_projections[v];14901491store_camera(projection, scene_data.projection[v]);1492store_camera(projection.inverse(), scene_data.inv_projection[v]);1493store_camera(p_reprojections[v], scene_data.reprojection[v]);1494scene_data.eye_offset[v][0] = p_eye_offsets[v].x;1495scene_data.eye_offset[v][1] = p_eye_offsets[v].y;1496scene_data.eye_offset[v][2] = p_eye_offsets[v].z;1497scene_data.eye_offset[v][3] = 0.0f;1498}14991500RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data);1501}15021503RID linear_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);1504RID nearest_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);15051506if (ssr_half_size) {1507RD::get_singleton()->draw_command_begin_label("SSR Downsample");15081509for (uint32_t v = 0; v < view_count; v++) {1510ScreenSpaceReflectionDownsamplePushConstant push_constant;1511push_constant.screen_size[0] = p_ssr_buffers.size.width;1512push_constant.screen_size[1] = p_ssr_buffers.size.height;15131514RID source_depth_texture = p_render_buffers->get_depth_texture(v);1515RID dest_depth_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0);1516RID dest_normal_roughness_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_NORMAL_ROUGHNESS, v, 0);15171518Size2i parent_size = RD::get_singleton()->texture_size(source_depth_texture);1519bool is_width_odd = (parent_size.width % 2) != 0;1520bool is_height_odd = (parent_size.height % 2) != 0;15211522int32_t downsample_mode;1523if (is_width_odd && is_height_odd) {1524downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH_AND_HEIGHT;1525} else if (is_width_odd) {1526downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_WIDTH;1527} else if (is_height_odd) {1528downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_ODD_HEIGHT;1529} else {1530downsample_mode = SCREEN_SPACE_REFLECTION_DOWNSAMPLE_DEFAULT;1531}15321533RID downsample_shader = ssr.downsample_shader.version_get_shader(ssr.downsample_shader_version, downsample_mode);15341535RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ nearest_sampler, source_depth_texture });1536RD::Uniform u_source_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>{ nearest_sampler, p_normal_roughness_slices[v] });1537RD::Uniform u_dest_depth(RD::UNIFORM_TYPE_IMAGE, 2, dest_depth_texture);1538RD::Uniform u_dest_normal_roughness(RD::UNIFORM_TYPE_IMAGE, 3, dest_normal_roughness_texture);15391540RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();15411542RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.downsample_pipelines[downsample_mode].get_rid());1543RD::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);1544RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));1545RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.screen_size[0], push_constant.screen_size[1], 1);15461547RD::get_singleton()->compute_list_end();1548}15491550RD::get_singleton()->draw_command_end_label();1551} else {1552RD::get_singleton()->draw_command_begin_label("SSR Copy Depth");15531554for (uint32_t v = 0; v < view_count; v++) {1555RID src_texture = p_render_buffers->get_depth_texture(v);1556RID dest_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0);1557p_copy_effects.copy_depth_to_rect(src_texture, dest_texture, Rect2i(Vector2i(), p_ssr_buffers.size));1558}15591560RD::get_singleton()->draw_command_end_label();1561}15621563RD::get_singleton()->draw_command_begin_label("SSR HI-Z");15641565for (uint32_t v = 0; v < view_count; v++) {1566for (uint32_t m = 1; m < p_ssr_buffers.mipmaps; m++) {1567ScreenSpaceReflectionHizPushConstant push_constant;1568push_constant.screen_size[0] = MAX(1, p_ssr_buffers.size.width >> m);1569push_constant.screen_size[1] = MAX(1, p_ssr_buffers.size.height >> m);15701571RID source;15721573if (!ssr_half_size && m == 1) { // Reuse the depth texture to not create a dependency on the previous depth copy pass.1574source = p_render_buffers->get_depth_texture(v);1575} else {1576source = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, m - 1);1577}15781579RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, m);15801581Size2i parent_size = RD::get_singleton()->texture_size(source);1582bool is_width_odd = (parent_size.width % 2) != 0;1583bool is_height_odd = (parent_size.height % 2) != 0;15841585int32_t hiz_mode;1586if (is_width_odd && is_height_odd) {1587hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH_AND_HEIGHT;1588} else if (is_width_odd) {1589hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_ODD_WIDTH;1590} else if (is_height_odd) {1591hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_ODD_HEIGHT;1592} else {1593hiz_mode = SCREEN_SPACE_REFLECTION_HIZ_DEFAULT;1594}15951596RID hiz_shader = ssr.hiz_shader.version_get_shader(ssr.hiz_shader_version, hiz_mode);15971598RD::Uniform u_source(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ nearest_sampler, source });1599RD::Uniform u_dest(RD::UNIFORM_TYPE_IMAGE, 1, dest);16001601RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();16021603RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.hiz_pipelines[hiz_mode].get_rid());1604RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(hiz_shader, 0, u_source, u_dest), 0);1605RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));1606RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.screen_size[0], push_constant.screen_size[1], 1);16071608RD::get_singleton()->compute_list_end();1609}1610}16111612RD::get_singleton()->draw_command_end_label();16131614RD::get_singleton()->draw_command_begin_label("SSR Main");16151616RID ssr_shader = ssr.ssr_shader.version_get_shader(ssr.ssr_shader_version, 0);16171618for (uint32_t v = 0; v < view_count; v++) {1619RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();16201621RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.ssr_pipeline.get_rid());16221623ScreenSpaceReflectionPushConstant push_constant;1624push_constant.screen_size[0] = p_ssr_buffers.size.width;1625push_constant.screen_size[1] = p_ssr_buffers.size.height;1626push_constant.mipmaps = p_ssr_buffers.mipmaps;1627push_constant.num_steps = p_max_steps;1628push_constant.curve_fade_in = p_fade_in;1629push_constant.distance_fade = p_fade_out;1630push_constant.depth_tolerance = p_tolerance;1631push_constant.orthogonal = p_projections[v].is_orthogonal();1632push_constant.view_index = v;16331634RID last_frame_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, 0);1635if (ssr_half_size && RD::get_singleton()->texture_size(last_frame_texture) != p_ssr_buffers.size) {1636// SSIL is likely also enabled. The texture we need is in the second mipmap in this case.1637last_frame_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSLF, RB_LAST_FRAME, v, 1);1638}16391640RID hiz_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0, 1, p_ssr_buffers.mipmaps);1641RID 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];1642RID ssr_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, 0);1643RID mip_level_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_MIP_LEVEL, v, 0);16441645RD::Uniform u_last_frame(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ linear_sampler, last_frame_texture });1646RD::Uniform u_hiz(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>{ nearest_sampler, hiz_texture });1647RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 2, Vector<RID>{ nearest_sampler, normal_roughness_texture });1648RD::Uniform u_ssr(RD::UNIFORM_TYPE_IMAGE, 3, ssr_texture);1649RD::Uniform u_mip_level(RD::UNIFORM_TYPE_IMAGE, 4, mip_level_texture);1650RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 5, ssr.ubo);1651RD::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);16521653RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));1654RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssr_buffers.size.width, p_ssr_buffers.size.height, 1);16551656RD::get_singleton()->compute_list_end();1657}16581659RD::get_singleton()->draw_command_end_label();16601661RD::get_singleton()->draw_command_begin_label("SSR Roughness Filter");16621663RID filter_shader = ssr.filter_shader.version_get_shader(ssr.filter_shader_version, 0);16641665for (uint32_t v = 0; v < view_count; v++) {1666for (uint32_t m = 1; m < p_ssr_buffers.mipmaps; m++) {1667ScreenSpaceReflectionFilterPushConstant push_constant;1668push_constant.screen_size[0] = MAX(1, p_ssr_buffers.size.width >> m);1669push_constant.screen_size[1] = MAX(1, p_ssr_buffers.size.height >> m);1670push_constant.mip_level = m;16711672RID source = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, m - 1);1673RID dest = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, m);16741675RD::Uniform u_source(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ linear_sampler, source });1676RD::Uniform u_dest(RD::UNIFORM_TYPE_IMAGE, 1, dest);16771678RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();16791680RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.filter_pipeline.get_rid());1681RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(filter_shader, 0, u_source, u_dest), 0);1682RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));1683RD::get_singleton()->compute_list_dispatch_threads(compute_list, push_constant.screen_size[0], push_constant.screen_size[1], 1);16841685RD::get_singleton()->compute_list_end();1686}1687}16881689RD::get_singleton()->draw_command_end_label();16901691if (ssr_half_size) {1692RD::get_singleton()->draw_command_begin_label("SSR Resolve");16931694RID resolve_shader = ssr.resolve_shader.version_get_shader(ssr.resolve_shader_version, 0);16951696for (uint32_t v = 0; v < view_count; v++) {1697RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();16981699RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.resolve_pipeline.get_rid());17001701Vector2i internal_size = p_render_buffers->get_internal_size();17021703ScreenSpaceReflectionResolvePushConstant push_constant;1704push_constant.screen_size[0] = internal_size.x;1705push_constant.screen_size[1] = internal_size.y;17061707RID depth_texture = p_render_buffers->get_depth_texture(v);1708RID depth_half_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_HIZ, v, 0);1709RID normal_roughness_half_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_NORMAL_ROUGHNESS, v, 0);1710RID ssr_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_SSR, v, 0, 1, p_ssr_buffers.mipmaps);1711RID mip_level_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_MIP_LEVEL, v, 0);1712RID output_texture = p_render_buffers->get_texture_slice(RB_SCOPE_SSR, RB_FINAL, v, 0);17131714RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>{ nearest_sampler, depth_texture });1715RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>{ nearest_sampler, p_normal_roughness_slices[v] });1716RD::Uniform u_depth_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 2, Vector<RID>{ nearest_sampler, depth_half_texture });1717RD::Uniform u_normal_roughness_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 3, Vector<RID>{ nearest_sampler, normal_roughness_half_texture });1718RD::Uniform u_ssr(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, Vector<RID>{ linear_sampler, ssr_texture });1719RD::Uniform u_mip_level(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 5, Vector<RID>{ nearest_sampler, mip_level_texture });1720RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 6, output_texture);1721RD::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);17221723RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(push_constant));1724RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.width, internal_size.height, 1);17251726RD::get_singleton()->compute_list_end();1727}17281729RD::get_singleton()->draw_command_end_label();1730}1731}17321733/* Subsurface scattering */17341735void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) {1736sss_quality = p_quality;1737}17381739RS::SubSurfaceScatteringQuality SSEffects::sss_get_quality() const {1740return sss_quality;1741}17421743void SSEffects::sss_set_scale(float p_scale, float p_depth_scale) {1744sss_scale = p_scale;1745sss_depth_scale = p_depth_scale;1746}17471748void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size) {1749UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();1750ERR_FAIL_NULL(uniform_set_cache);1751MaterialStorage *material_storage = MaterialStorage::get_singleton();1752ERR_FAIL_NULL(material_storage);17531754RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);17551756// Our intermediate buffer is only created if we haven't created it already.1757RD::DataFormat format = p_render_buffers->get_base_data_format();1758uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;1759uint32_t layers = 1; // We only need one layer, we're handling one view at a time1760uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);1761RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);17621763Plane p = p_camera.xform4(Plane(1, 0, -1, 1));1764p.normal /= p.d;1765float unit_size = p.normal.x;17661767{ //scale color and depth to half1768RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();17691770sss.push_constant.camera_z_far = p_camera.get_z_far();1771sss.push_constant.camera_z_near = p_camera.get_z_near();1772sss.push_constant.orthogonal = p_camera.is_orthogonal();1773sss.push_constant.unit_size = unit_size;1774sss.push_constant.screen_size[0] = p_screen_size.x;1775sss.push_constant.screen_size[1] = p_screen_size.y;1776sss.push_constant.vertical = false;1777sss.push_constant.scale = sss_scale;1778sss.push_constant.depth_scale = sss_depth_scale;17791780RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1);1781RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1].get_rid());17821783RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));1784RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));1785RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));1786RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));1787RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));17881789// horizontal17901791RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);1792RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);1793RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);17941795RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));17961797RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);17981799RD::get_singleton()->compute_list_add_barrier(compute_list);18001801// vertical18021803RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);1804RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);1805RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);18061807sss.push_constant.vertical = true;1808RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));18091810RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);18111812RD::get_singleton()->compute_list_end();1813}1814}181518161817