diff options
Diffstat (limited to 'servers/rendering/renderer_rd/environment')
-rw-r--r-- | servers/rendering/renderer_rd/environment/fog.cpp | 300 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/environment/fog.h | 139 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/environment/gi.cpp | 647 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/environment/gi.h | 303 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/environment/sky.cpp | 647 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/environment/sky.h | 150 |
6 files changed, 1037 insertions, 1149 deletions
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index fba04c0db4..2787693aeb 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* fog.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* fog.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #include "fog.h" @@ -57,12 +57,19 @@ void Fog::fog_volume_initialize(RID p_rid) { fog_volume_owner.initialize_rid(p_rid, FogVolume()); } -void Fog::fog_free(RID p_rid) { +void Fog::fog_volume_free(RID p_rid) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid); fog_volume->dependency.deleted_notify(p_rid); fog_volume_owner.free(p_rid); } +Dependency *Fog::fog_volume_get_dependency(RID p_fog_volume) const { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_NULL_V(fog_volume, nullptr); + + return &fog_volume->dependency; +} + void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); ERR_FAIL_COND(!fog_volume); @@ -122,8 +129,6 @@ AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); } } - - return AABB(); } Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { @@ -138,30 +143,30 @@ Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { uniform_set_updated = true; - return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true); } Fog::FogMaterialData::~FogMaterialData() { free_parameters_uniform_set(uniform_set); } -RendererRD::ShaderData *Fog::_create_fog_shader_func() { +RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() { FogShaderData *shader_data = memnew(FogShaderData); return shader_data; } -RendererRD::ShaderData *Fog::_create_fog_shader_funcs() { +RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() { return Fog::get_singleton()->_create_fog_shader_func(); }; -RendererRD::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) { FogMaterialData *material_data = memnew(FogMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererRD::MaterialData *Fog::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader)); }; @@ -190,8 +195,8 @@ void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_lay volumetric_fog_modes.push_back(""); volumetric_fog.shader.initialize(volumetric_fog_modes); - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs); volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO)); } @@ -246,7 +251,7 @@ ALBEDO = vec3(1.0); material_storage->material_initialize(volumetric_fog.default_material); material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader); - FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG)); + FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -314,10 +319,6 @@ void Fog::free_fog_shader() { material_storage->material_free(volumetric_fog.default_material); } -void Fog::FogShaderData::set_path_hint(const String &p_path) { - path = p_path; -} - void Fog::FogShaderData::set_code(const String &p_code) { //compile @@ -361,83 +362,6 @@ void Fog::FogShaderData::set_code(const String &p_code) { valid = true; } -void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void Fog::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - RBMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool Fog::FogShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool Fog::FogShaderData::is_animated() const { return false; } @@ -446,15 +370,6 @@ bool Fog::FogShaderData::casts_shadows() const { return false; } -Variant Fog::FogShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const { Fog *fog_singleton = Fog::get_singleton(); @@ -473,7 +388,7 @@ Fog::FogShaderData::~FogShaderData() { //////////////////////////////////////////////////////////////////////////////// // Volumetric Fog -Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) { +void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) { width = fog_size.x; height = fog_size.y; depth = fog_size.z; @@ -500,7 +415,7 @@ Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) { fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView()); RD::get_singleton()->set_resource_name(fog_map, "Fog map"); -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) Vector<uint8_t> dm; dm.resize(fog_size.x * fog_size.y * fog_size.z * 4); dm.fill(0); @@ -591,6 +506,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RENDER_TIMESTAMP("> Volumetric Fog"); RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); + Ref<VolumetricFog> fog = p_settings.vfog; + if (p_fog_volumes.size() > 0) { RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); @@ -623,9 +540,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P params.z_far = z_far; params.time = p_settings.time; - params.fog_volume_size[0] = p_settings.vfog->width; - params.fog_volume_size[1] = p_settings.vfog->height; - params.fog_volume_size[2] = p_settings.vfog->depth; + params.fog_volume_size[0] = fog->width; + params.fog_volume_size[1] = fog->height; + params.fog_volume_size[2] = fog->depth; params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env); params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; @@ -638,18 +555,18 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); - if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) { + if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) { Vector<RD::Uniform> uniforms; { RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; #else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 1; - u.append_id(p_settings.vfog->emissive_map); + u.append_id(fog->emissive_map); uniforms.push_back(u); } @@ -663,29 +580,29 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P { RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; #else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 3; - u.append_id(p_settings.vfog->density_map); + u.append_id(fog->density_map); uniforms.push_back(u); } { RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; #else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 4; - u.append_id(p_settings.vfog->light_map); + u.append_id(fog->light_map); uniforms.push_back(u); } - p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); } RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -701,7 +618,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P FogMaterialData *material = nullptr; if (fog_material.is_valid()) { - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -709,7 +626,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (!material) { fog_material = volumetric_fog.default_material; - material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG)); + material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG)); } ERR_FAIL_COND(!material); @@ -720,9 +637,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P any_uses_time |= shader_data->uses_time; - Vector3i min = Vector3i(); - Vector3i max = Vector3i(); - Vector3i kernel_size = Vector3i(); + Vector3i min; + Vector3i max; + Vector3i kernel_size; Vector3 position = fog_volume_instance->transform.get_origin(); RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); @@ -731,7 +648,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { // Local fog volume. Vector3i points[8]; - Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth); float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); @@ -742,7 +659,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1); + min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1); max = Vector3i(1, 1, 1); for (int j = 0; j < 8; j++) { @@ -753,9 +670,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P kernel_size = max - min; } else { // Volume type global runs on all cells - extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + extents = Vector3(fog->width, fog->height, fog->depth); min = Vector3i(0, 0, 0); - kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth)); + kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth)); } if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { @@ -777,11 +694,12 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant)); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL); + material->set_as_used(); } RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z); @@ -795,7 +713,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_end(); } - if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) { + if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) { //re create uniform set if needed Vector<RD::Uniform> uniforms; Vector<RD::Uniform> copy_uniforms; @@ -805,7 +723,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; if (p_settings.shadow_atlas_depth.is_null()) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); } else { u.append_id(p_settings.shadow_atlas_depth); } @@ -821,7 +739,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (p_settings.directional_shadow_depth.is_valid()) { u.append_id(p_settings.directional_shadow_depth); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK)); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -875,7 +793,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; - u.append_id(p_settings.vfog->light_density_map); + u.append_id(fog->light_density_map); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -884,7 +802,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(p_settings.vfog->fog_map); + u.append_id(fog->fog_map); uniforms.push_back(u); } @@ -892,7 +810,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(p_settings.vfog->prev_light_density_map); + u.append_id(fog->prev_light_density_map); copy_uniforms.push_back(u); } @@ -909,7 +827,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 11; - u.append_id(p_settings.voxel_gl_buffer); + u.append_id(p_settings.voxel_gi_buffer); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -944,41 +862,41 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 15; - u.append_id(p_settings.vfog->prev_light_density_map); + u.append_id(fog->prev_light_density_map); uniforms.push_back(u); } { RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; #else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 16; - u.append_id(p_settings.vfog->density_map); + u.append_id(fog->density_map); uniforms.push_back(u); } { RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; #else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 17; - u.append_id(p_settings.vfog->light_map); + u.append_id(fog->light_map); uniforms.push_back(u); } { RD::Uniform u; -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; #else u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 18; - u.append_id(p_settings.vfog->emissive_map); + u.append_id(fog->emissive_map); uniforms.push_back(u); } @@ -986,15 +904,15 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 19; - RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RID sky_texture = RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env).is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env)) : RID(); u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture); uniforms.push_back(u); } - p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); + fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); - p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); RID aux7 = uniforms.write[7].get_id(0); RID aux8 = uniforms.write[8].get_id(0); @@ -1002,17 +920,17 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P uniforms.write[7].set_id(0, aux8); uniforms.write[8].set_id(0, aux7); - p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); uniforms.remove_at(8); uniforms.write[7].set_id(0, aux7); - p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); + fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); } - bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi != nullptr); + bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi.is_valid()); if (using_sdfgi) { - if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) { + if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) { Vector<RD::Uniform> uniforms; { @@ -1039,12 +957,12 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P uniforms.push_back(u); } - p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); + fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); } } - p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); - p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); + fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); + fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); VolumetricFogShader::ParamsUBO params; @@ -1079,9 +997,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P params.ambient_color[2] = ambient_color.b; params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env); - params.fog_volume_size[0] = p_settings.vfog->width; - params.fog_volume_size[1] = p_settings.vfog->height; - params.fog_volume_size[2] = p_settings.vfog->depth; + params.fog_volume_size[0] = fog->width; + params.fog_volume_size[1] = fog->height; + params.fog_volume_size[2] = fog->depth; params.directional_light_count = p_directional_light_count; @@ -1149,19 +1067,19 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0); if (using_sdfgi) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1); } - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_add_barrier(compute_list); // Copy fog to history buffer if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) { RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_add_barrier(compute_list); } RD::get_singleton()->draw_command_end_label(); @@ -1172,8 +1090,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RENDER_TIMESTAMP("Filter Fog"); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_end(); //need restart for buffer update @@ -1183,8 +1101,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set2, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_add_barrier(compute_list); RD::get_singleton()->draw_command_end_label(); @@ -1194,8 +1112,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->draw_command_begin_label("Integrate Fog"); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1); RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index e777a1d383..eb0a2fc7b5 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* fog.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* fog.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #ifndef FOG_RD_H #define FOG_RD_H @@ -38,12 +38,17 @@ #include "servers/rendering/renderer_rd/environment/gi.h" #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h" #include "servers/rendering/storage/utilities.h" +#define RB_SCOPE_FOG SNAME("Fog") + namespace RendererRD { class Fog : public RendererFog { -public: +private: + static Fog *singleton; + /* FOG VOLUMES */ struct FogVolume { @@ -55,16 +60,14 @@ public: Dependency dependency; }; + mutable RID_Owner<FogVolume, true> fog_volume_owner; + struct FogVolumeInstance { RID volume; Transform3D transform; bool active = false; }; -private: - static Fog *singleton; - - mutable RID_Owner<FogVolume, true> fog_volume_owner; mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner; /* Volumetric Fog */ @@ -180,39 +183,30 @@ private: Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform); - struct FogShaderData : public RendererRD::ShaderData { + struct FogShaderData : public RendererRD::MaterialStorage::ShaderData { bool valid = false; RID version; RID pipeline; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; - String path; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; - virtual void set_path_hint(const String &p_hint); virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; FogShaderData() {} virtual ~FogShaderData(); }; - struct FogMaterialData : public RendererRD::MaterialData { + struct FogMaterialData : public RendererRD::MaterialStorage::MaterialData { FogShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -223,11 +217,11 @@ private: virtual ~FogMaterialData(); }; - RendererRD::ShaderData *_create_fog_shader_func(); - static RendererRD::ShaderData *_create_fog_shader_funcs(); + RendererRD::MaterialStorage::ShaderData *_create_fog_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_fog_shader_funcs(); - RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader); - static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader); + RendererRD::MaterialStorage::MaterialData *_create_fog_material_func(FogShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader); public: static Fog *get_singleton() { return singleton; } @@ -237,12 +231,12 @@ public: /* FOG VOLUMES */ - FogVolume *get_fog_volume(RID p_rid) { return fog_volume_owner.get_or_null(p_rid); }; bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }; virtual RID fog_volume_allocate() override; virtual void fog_volume_initialize(RID p_rid) override; - virtual void fog_free(RID p_rid) override; + virtual void fog_volume_free(RID p_rid) override; + Dependency *fog_volume_get_dependency(RID p_fog_volume) const; virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; @@ -254,14 +248,40 @@ public: /* FOG VOLUMES INSTANCE */ - FogVolumeInstance *get_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.get_or_null(p_rid); }; bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }; RID fog_volume_instance_create(RID p_fog_volume); void fog_instance_free(RID p_rid); + void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND(!fvi); + fvi->transform = p_transform; + } + + void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND(!fvi); + fvi->active = p_active; + } + + RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND_V(!fvi, RID()); + return fvi->volume; + } + + Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const { + Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance); + ERR_FAIL_COND_V(!fvi, Vector3()); + return fvi->transform.get_origin(); + } + /* Volumetric FOG */ - struct VolumetricFog { + class VolumetricFog : public RenderBufferCustomDataRD { + GDCLASS(VolumetricFog, RenderBufferCustomDataRD) + + public: enum { MAX_TEMPORAL_FRAMES = 16 }; @@ -290,7 +310,10 @@ public: int last_shadow_filter = -1; - VolumetricFog(const Vector3i &fog_size, RID p_sky_shader); + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; + virtual void free_data() override{}; + + void init(const Vector3i &fog_size, RID p_sky_shader); ~VolumetricFog(); }; @@ -304,7 +327,7 @@ public: uint32_t max_cluster_elements; bool volumetric_fog_filter_active; RID shadow_sampler; - RID voxel_gl_buffer; + RID voxel_gi_buffer; RID shadow_atlas_depth; RID omni_light_buffer; RID spot_light_buffer; @@ -312,11 +335,11 @@ public: RID directional_light_buffer; // Objects related to our render buffer - VolumetricFog *vfog; + Ref<VolumetricFog> vfog; ClusterBuilderRD *cluster_builder; GI *gi; - GI::SDFGI *sdfgi; - GI::RenderBuffersGI *rbgi; + Ref<GI::SDFGI> sdfgi; + Ref<GI::RenderBuffersGI> rbgi; RID env; SkyRD *sky; }; diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 7b4f61bd17..a52716cd78 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gi.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* gi.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #include "gi.h" @@ -34,6 +34,7 @@ #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" @@ -287,6 +288,19 @@ float GI::voxel_gi_get_energy(RID p_voxel_gi) const { return voxel_gi->energy; } +void GI::voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->baked_exposure = p_baked_exposure; +} + +float GI::voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->baked_exposure; +} + void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) { VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); ERR_FAIL_COND(!voxel_gi); @@ -371,6 +385,13 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) { return voxel_gi->sdf_texture; } +Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, nullptr); + + return &voxel_gi->dependency; +} + //////////////////////////////////////////////////////////////////////////////// // SDFGI @@ -734,7 +755,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -978,7 +999,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -991,7 +1012,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1004,7 +1025,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1017,7 +1038,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re if (j < cascades.size()) { u.append_id(cascades[j].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1108,7 +1129,11 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env); } -void GI::SDFGI::erase() { +void GI::SDFGI::free_data() { + // we don't free things here, we handle SDFGI differently at the moment destructing the object when it needs to change. +} + +GI::SDFGI::~SDFGI() { for (uint32_t i = 0; i < cascades.size(); i++) { const SDFGI::Cascade &c = cascades[i]; RD::get_singleton()->free(c.light_data); @@ -1140,6 +1165,7 @@ void GI::SDFGI::erase() { RD::get_singleton()->free(lightprobe_data); RD::get_singleton()->free(lightprobe_history_scroll); + RD::get_singleton()->free(lightprobe_average_scroll); RD::get_singleton()->free(occlusion_data); RD::get_singleton()->free(ambient_texture); @@ -1291,7 +1317,7 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) { push_constant.y_mult = y_mult; if (reads_sky && p_env.is_valid()) { - push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); + push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy_multiplier(p_env); if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) { push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; @@ -1498,7 +1524,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1511,7 +1537,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1524,7 +1550,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1537,7 +1563,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection if (i < cascades.size()) { u.append_id(cascades[i].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -1591,34 +1617,24 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection push_constant.max_cascades = cascades.size(); push_constant.screen_size[0] = p_width; push_constant.screen_size[1] = p_height; - push_constant.probe_axis_size = probe_axis_count; - push_constant.use_occlusion = uses_occlusion; push_constant.y_mult = y_mult; push_constant.z_near = -p_projections[v].get_z_near(); - push_constant.cam_transform[0] = p_transform.basis.rows[0][0]; - push_constant.cam_transform[1] = p_transform.basis.rows[1][0]; - push_constant.cam_transform[2] = p_transform.basis.rows[2][0]; - push_constant.cam_transform[3] = 0; - push_constant.cam_transform[4] = p_transform.basis.rows[0][1]; - push_constant.cam_transform[5] = p_transform.basis.rows[1][1]; - push_constant.cam_transform[6] = p_transform.basis.rows[2][1]; - push_constant.cam_transform[7] = 0; - push_constant.cam_transform[8] = p_transform.basis.rows[0][2]; - push_constant.cam_transform[9] = p_transform.basis.rows[1][2]; - push_constant.cam_transform[10] = p_transform.basis.rows[2][2]; - push_constant.cam_transform[11] = 0; - push_constant.cam_transform[12] = p_transform.origin.x; - push_constant.cam_transform[13] = p_transform.origin.y; - push_constant.cam_transform[14] = p_transform.origin.z; - push_constant.cam_transform[15] = 1; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + push_constant.cam_basis[i][j] = p_transform.basis.rows[j][i]; + } + } + push_constant.cam_origin[0] = p_transform.origin[0]; + push_constant.cam_origin[1] = p_transform.origin[1]; + push_constant.cam_origin[2] = p_transform.origin[2]; // need to properly unproject for asymmetric projection matrices in stereo.. Projection inv_projection = p_projections[v].inverse(); for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - push_constant.inv_projection[i * 4 + j] = inv_projection.matrix[i][j]; + for (int j = 0; j < 3; j++) { + push_constant.inv_projection[j][i] = inv_projection.columns[i][j]; } } @@ -1628,8 +1644,8 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projection RD::get_singleton()->compute_list_end(); } - Size2 rtsize = texture_storage->render_target_get_size(p_render_target); - copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1); + Size2i rtsize = texture_storage->render_target_get_size(p_render_target); + copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2i(Point2i(), rtsize), true, false, false, false, RID(), p_view_count > 1); } void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { @@ -1782,7 +1798,8 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con RD::get_singleton()->draw_list_end(); } -void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); /* Update general SDFGI Buffer */ SDFGIData sdfgi_data; @@ -1849,6 +1866,11 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r c.probe_world_offset[2] = probe_ofs.z; c.to_cell = 1.0 / cascades[i].cell_size; + c.exposure_normalization = 1.0; + if (p_render_data->camera_attributes.is_valid()) { + float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + c.exposure_normalization = exposure_normalization / cascades[i].baked_exposure_normalization; + } } RD::get_singleton()->buffer_update(gi->sdfgi_ubo, 0, sizeof(SDFGIData), &sdfgi_data, RD::BARRIER_MASK_COMPUTE); @@ -1860,32 +1882,43 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r SDFGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS]; uint32_t idx = 0; - for (uint32_t j = 0; j < (uint32_t)p_scene_render->render_state.sdfgi_update_data->directional_lights->size(); j++) { + for (uint32_t j = 0; j < (uint32_t)p_render_data->sdfgi_update_data->directional_lights->size(); j++) { if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { break; } - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j)); - ERR_CONTINUE(!li); + RID light_instance = p_render_data->sdfgi_update_data->directional_lights->get(j); + ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); + + RID light = light_storage->light_instance_get_base_light(light_instance); + Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); - if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { + if (RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { continue; } - Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); + Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z); dir.y *= y_mult; dir.normalize(); lights[idx].direction[0] = dir.x; lights[idx].direction[1] = dir.y; lights[idx].direction[2] = dir.z; - Color color = RSG::light_storage->light_get_color(li->light); + Color color = RSG::light_storage->light_get_color(light); color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; lights[idx].type = RS::LIGHT_DIRECTIONAL; - lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); - lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); + lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); + } + + if (p_render_data->camera_attributes.is_valid()) { + lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + } + + lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); idx++; } @@ -1894,47 +1927,69 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascade.position)) * cascade.cell_size; cascade_aabb.size = Vector3(1, 1, 1) * cascade_size * cascade.cell_size; - for (uint32_t j = 0; j < p_scene_render->render_state.sdfgi_update_data->positional_light_count; j++) { + for (uint32_t j = 0; j < p_render_data->sdfgi_update_data->positional_light_count; j++) { if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { break; } - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]); - ERR_CONTINUE(!li); + RID light_instance = p_render_data->sdfgi_update_data->positional_light_instances[j]; + ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); + + RID light = light_storage->light_instance_get_base_light(light_instance); + AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance); + Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); - uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light); + uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light); if (i > max_sdfgi_cascade) { continue; } - if (!cascade_aabb.intersects(li->aabb)) { + if (!cascade_aabb.intersects(light_aabb)) { continue; } - Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); + Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z); //faster to not do this here //dir.y *= y_mult; //dir.normalize(); lights[idx].direction[0] = dir.x; lights[idx].direction[1] = dir.y; lights[idx].direction[2] = dir.z; - Vector3 pos = li->transform.origin; + Vector3 pos = light_transform.origin; pos.y *= y_mult; lights[idx].position[0] = pos.x; lights[idx].position[1] = pos.y; lights[idx].position[2] = pos.z; - Color color = RSG::light_storage->light_get_color(li->light); + Color color = RSG::light_storage->light_get_color(light); color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; - lights[idx].type = RSG::light_storage->light_get_type(li->light); - lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); - lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); - lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); - lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); - lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + lights[idx].type = RSG::light_storage->light_get_type(light); + + lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); + + // Convert from Luminous Power to Luminous Intensity + if (lights[idx].type == RS::LIGHT_OMNI) { + lights[idx].energy *= 1.0 / (Math_PI * 4.0); + } else if (lights[idx].type == RS::LIGHT_SPOT) { + // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. + // We make this assumption to keep them easy to control. + lights[idx].energy *= 1.0 / Math_PI; + } + } + + if (p_render_data->camera_attributes.is_valid()) { + lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + } + + lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); + lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); + lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; } @@ -1947,10 +2002,9 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r } } -void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization) { //print_line("rendering region " + itos(p_region)); - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... + ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but... AABB bounds; Vector3i from; Vector3i size; @@ -1969,7 +2023,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr } //print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(cascades[cascade].cell_size)); - p_scene_render->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing); + RendererSceneRenderRD::get_singleton()->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing, p_exposure_normalization); if (cascade_next != cascade) { RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade"); @@ -1998,6 +2052,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr } cascades[cascade].all_dynamic_lights_dirty = true; + cascades[cascade].baked_exposure_normalization = p_exposure_normalization; push_constant.grid_size = cascade_size; push_constant.cascade = cascade; @@ -2280,7 +2335,7 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr img.instantiate(); for (uint32_t i = 0; i < cascade_size; i++) { Vector<uint8_t> subarr = data.slice(128 * 128 * i, 128 * 128 * (i + 1)); - img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr); + img->set_data(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr); img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png"); } @@ -2306,9 +2361,10 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr } } -void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) { - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... +void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) { + ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but... + + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights"); @@ -2335,21 +2391,25 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co break; } - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]); - ERR_CONTINUE(!li); + RID light_instance = p_positional_light_cull_result[i][j]; + ERR_CONTINUE(!light_storage->owns_light_instance(light_instance)); + + RID light = light_storage->light_instance_get_base_light(light_instance); + AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance); + Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance); - uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light); + uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light); if (p_cascade_indices[i] > max_sdfgi_cascade) { continue; } - if (!cascade_aabb.intersects(li->aabb)) { + if (!cascade_aabb.intersects(light_aabb)) { continue; } - lights[idx].type = RSG::light_storage->light_get_type(li->light); + lights[idx].type = RSG::light_storage->light_get_type(light); - Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z); + Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z); if (lights[idx].type == RS::LIGHT_DIRECTIONAL) { dir.y *= y_mult; //only makes sense for directional dir.normalize(); @@ -2357,22 +2417,40 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co lights[idx].direction[0] = dir.x; lights[idx].direction[1] = dir.y; lights[idx].direction[2] = dir.z; - Vector3 pos = li->transform.origin; + Vector3 pos = light_transform.origin; pos.y *= y_mult; lights[idx].position[0] = pos.x; lights[idx].position[1] = pos.y; lights[idx].position[2] = pos.z; - Color color = RSG::light_storage->light_get_color(li->light); + Color color = RSG::light_storage->light_get_color(light); color = color.srgb_to_linear(); lights[idx].color[0] = color.r; lights[idx].color[1] = color.g; lights[idx].color[2] = color.b; - lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY); - lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); - lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); - lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); - lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); + + // Convert from Luminous Power to Luminous Intensity + if (lights[idx].type == RS::LIGHT_OMNI) { + lights[idx].energy *= 1.0 / (Math_PI * 4.0); + } else if (lights[idx].type == RS::LIGHT_SPOT) { + // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. + // We make this assumption to keep them easy to control. + lights[idx].energy *= 1.0 / Math_PI; + } + } + + if (p_render_data->camera_attributes.is_valid()) { + lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + } + + lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light); + lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); + lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; } @@ -2428,7 +2506,8 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co //////////////////////////////////////////////////////////////////////////////// // VoxelGIInstance -void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); uint32_t data_version = gi->voxel_gi_get_data_version(probe); @@ -2437,18 +2516,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID if (last_probe_data_version != data_version) { //need to re-create everything - if (texture.is_valid()) { - RD::get_singleton()->free(texture); - RD::get_singleton()->free(write_buffer); - mipmaps.clear(); - } - - for (int i = 0; i < dynamic_maps.size(); i++) { - RD::get_singleton()->free(dynamic_maps[i].texture); - RD::get_singleton()->free(dynamic_maps[i].depth); - } - - dynamic_maps.clear(); + free_resources(); Vector3i octree_size = gi->voxel_gi_get_octree_size(probe); @@ -2781,7 +2849,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID last_probe_data_version = data_version; p_update_light_instances = true; //just in case - p_scene_render->_base_uniforms_changed(); + RendererSceneRenderRD::get_singleton()->base_uniforms_changed(); } // UDPDATE TIME @@ -2798,13 +2866,14 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID { Transform3D to_cell = gi->voxel_gi_get_to_cell_xform(probe); - Transform3D to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse(); + Transform3D to_probe_xform = to_cell * transform.affine_inverse(); + //update lights for (uint32_t i = 0; i < light_count; i++) { VoxelGILight &l = gi->voxel_gi_lights[i]; RID light_instance = p_light_instances[i]; - RID light = p_scene_render->light_instance_get_base_light(light_instance); + RID light = light_storage->light_instance_get_base_light(light_instance); l.type = RSG::light_storage->light_get_type(light); if (l.type == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) { @@ -2814,16 +2883,32 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + l.energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY); + + l.energy *= gi->voxel_gi_get_baked_exposure_normalization(probe); + + // Convert from Luminous Power to Luminous Intensity + if (l.type == RS::LIGHT_OMNI) { + l.energy *= 1.0 / (Math_PI * 4.0); + } else if (l.type == RS::LIGHT_SPOT) { + // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle. + // We make this assumption to keep them easy to control. + l.energy *= 1.0 / Math_PI; + } + } + l.radius = to_cell.basis.xform(Vector3(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length(); Color color = RSG::light_storage->light_get_color(light).srgb_to_linear(); l.color[0] = color.r; l.color[1] = color.g; l.color[2] = color.b; - l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); + l.cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); - Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance); + Transform3D xform = light_storage->light_instance_get_base_transform(light_instance); Vector3 pos = to_probe_xform.xform(xform.origin); Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_column(2)).normalized(); @@ -3018,12 +3103,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID Projection cm; cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]); - if (p_scene_render->cull_argument.size() == 0) { - p_scene_render->cull_argument.push_back(nullptr); + if (RendererSceneRenderRD::get_singleton()->cull_argument.size() == 0) { + RendererSceneRenderRD::get_singleton()->cull_argument.push_back(nullptr); } - p_scene_render->cull_argument[0] = instance; + RendererSceneRenderRD::get_singleton()->cull_argument[0] = instance; - p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size)); + float exposure_normalization = 1.0; + if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) { + exposure_normalization = gi->voxel_gi_get_baked_exposure_normalization(probe); + } + + RendererSceneRenderRD::get_singleton()->_render_material(to_world_xform * xform, cm, true, RendererSceneRenderRD::get_singleton()->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size), exposure_normalization); VoxelGIDynamicPushConstant push_constant; memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant)); @@ -3140,6 +3230,37 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID last_probe_version = gi->voxel_gi_get_version(probe); } +void GI::VoxelGIInstance::free_resources() { + if (texture.is_valid()) { + RD::get_singleton()->free(texture); + RD::get_singleton()->free(write_buffer); + + texture = RID(); + write_buffer = RID(); + mipmaps.clear(); + } + + for (int i = 0; i < dynamic_maps.size(); i++) { + RD::get_singleton()->free(dynamic_maps[i].texture); + RD::get_singleton()->free(dynamic_maps[i].depth); + + // these only exist on the first level... + if (dynamic_maps[i].fb_depth.is_valid()) { + RD::get_singleton()->free(dynamic_maps[i].fb_depth); + } + if (dynamic_maps[i].albedo.is_valid()) { + RD::get_singleton()->free(dynamic_maps[i].albedo); + } + if (dynamic_maps[i].normal.is_valid()) { + RD::get_singleton()->free(dynamic_maps[i].normal); + } + if (dynamic_maps[i].orm.is_valid()) { + RD::get_singleton()->free(dynamic_maps[i].orm); + } + } + dynamic_maps.clear(); +} + void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3165,7 +3286,7 @@ void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, c for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - push_constant.projection[i * 4 + j] = cam_transform.matrix[i][j]; + push_constant.projection[i * 4 + j] = cam_transform.columns[i][j]; } } @@ -3353,9 +3474,9 @@ void GI::init(SkyRD *p_sky) { u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; if (p_sky->sky_use_cubemap_array) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE)); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); } uniforms.push_back(u); } @@ -3375,6 +3496,10 @@ void GI::init(SkyRD *p_sky) { { //calculate tables String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) { + defines += "\n#define USE_VRS\n"; + } + Vector<String> gi_modes; gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI @@ -3477,25 +3602,27 @@ void GI::free() { } } -GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { - SDFGI *sdfgi = memnew(SDFGI); +Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { + Ref<SDFGI> sdfgi; + sdfgi.instantiate(); sdfgi->create(p_env, p_world_position, p_requested_history_size, this); return sdfgi; } -void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { +void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used) { + ERR_FAIL_COND(p_render_buffers.is_null()); + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_NULL(texture_storage); r_voxel_gi_instances_used = 0; - // feels a little dirty to use our container this way but.... - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(rb == nullptr); - - RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers); + Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); + ERR_FAIL_COND(rbgi.is_null()); + RID voxel_gi_buffer = rbgi->get_voxel_gi_buffer(); VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES]; bool voxel_gi_instances_changed = false; @@ -3506,7 +3633,7 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { RID texture; if (i < (int)p_voxel_gi_instances.size()) { - VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]); + VoxelGIInstance *gipi = voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]); if (gipi) { texture = gipi->texture; @@ -3544,37 +3671,44 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra gipd.normal_bias = voxel_gi_get_normal_bias(base_probe); gipd.blend_ambient = !voxel_gi_is_interior(base_probe); gipd.mipmaps = gipi->mipmaps.size(); + gipd.exposure_normalization = 1.0; + if (p_render_data->camera_attributes.is_valid()) { + float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); + gipd.exposure_normalization = exposure_normalization / voxel_gi_get_baked_exposure_normalization(base_probe); + } } r_voxel_gi_instances_used++; } if (texture == RID()) { - texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } - if (texture != rb->rbgi.voxel_gi_textures[i]) { + if (texture != rbgi->voxel_gi_textures[i]) { voxel_gi_instances_changed = true; - rb->rbgi.voxel_gi_textures[i] = texture; + rbgi->voxel_gi_textures[i] = texture; } } if (voxel_gi_instances_changed) { for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - if (RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { - RD::get_singleton()->free(rb->rbgi.uniform_set[v]); + if (RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) { + RD::get_singleton()->free(rbgi->uniform_set[v]); } - rb->rbgi.uniform_set[v] = RID(); + rbgi->uniform_set[v] = RID(); } - if (rb->volumetric_fog) { - if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set); - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set); - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2); + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); + + if (RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) { + RD::get_singleton()->free(fog->fog_uniform_set); + RD::get_singleton()->free(fog->process_uniform_set); + RD::get_singleton()->free(fog->process_uniform_set2); } - rb->volumetric_fog->fog_uniform_set = RID(); - rb->volumetric_fog->process_uniform_set = RID(); - rb->volumetric_fog->process_uniform_set2 = RID(); + fog->fog_uniform_set = RID(); + fog->process_uniform_set = RID(); + fog->process_uniform_set2 = RID(); } } @@ -3587,7 +3721,14 @@ void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_tra } } -void GI::RenderBuffersGI::free() { +RID GI::RenderBuffersGI::get_voxel_gi_buffer() { + if (voxel_gi_buffer.is_null()) { + voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::VoxelGIData) * GI::MAX_VOXEL_GI_INSTANCES); + } + return voxel_gi_buffer; +} + +void GI::RenderBuffersGI::free_data() { for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) { RD::get_singleton()->free(uniform_set[v]); @@ -3600,28 +3741,13 @@ void GI::RenderBuffersGI::free() { scene_data_ubo = RID(); } - if (ambient_buffer.is_valid()) { - RD::get_singleton()->free(ambient_buffer); - RD::get_singleton()->free(reflection_buffer); - ambient_buffer = RID(); - reflection_buffer = RID(); - - // these are automatically freed when we free the textures, so just reset.. - for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - ambient_slice[v] = RID(); - reflection_slice[v] = RID(); - } - - view_count = 0; - } - if (voxel_gi_buffer.is_valid()) { RD::get_singleton()->free(voxel_gi_buffer); voxel_gi_buffer = RID(); } } -void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { +void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3629,65 +3755,38 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::get_singleton()->draw_command_begin_label("GI Render"); - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(rb == nullptr); + ERR_FAIL_COND(p_render_buffers.is_null()); - if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) { - // Free our old buffer if applicable - if (rb->rbgi.ambient_buffer.is_valid()) { - RD::get_singleton()->free(rb->rbgi.ambient_buffer); - RD::get_singleton()->free(rb->rbgi.reflection_buffer); + Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); + ERR_FAIL_COND(rbgi.is_null()); - for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - rb->rbgi.ambient_slice[v] = RID(); - rb->rbgi.reflection_slice[v] = RID(); - } - } + Size2i internal_size = p_render_buffers->get_internal_size(); + + if (rbgi->using_half_size_gi != half_resolution) { + p_render_buffers->clear_context(RB_SCOPE_GI); + } - // Remember the view count we're using - rb->rbgi.view_count = p_view_count; + if (!p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) { + Size2i size = internal_size; + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - // Create textures for our ambient and reflection data - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->internal_width; - tf.height = rb->internal_height; if (half_resolution) { - tf.width >>= 1; - tf.height >>= 1; - } - if (p_view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.array_layers = p_view_count; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - } - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer"); - rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer"); - rb->rbgi.using_half_size_gi = half_resolution; - - if (p_view_count == 1) { - // Just copy, we don't need to create slices - rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer; - rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer; - } else { - for (uint32_t v = 0; v < p_view_count; v++) { - rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); - rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); - } + size.x >>= 1; + size.y >>= 1; } + + p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_AMBIENT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size); + p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_REFLECTION, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size); + + rbgi->using_half_size_gi = half_resolution; } // Setup our scene data { SceneData scene_data; - if (rb->rbgi.scene_data_ubo.is_null()) { - rb->rbgi.scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData)); + if (rbgi->scene_data_ubo.is_null()) { + rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData)); } for (uint32_t v = 0; v < p_view_count; v++) { @@ -3701,10 +3800,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, // Note that we will be ignoring the origin of this transform. RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform); - scene_data.screen_size[0] = rb->internal_width; - scene_data.screen_size[1] = rb->internal_height; + scene_data.screen_size[0] = internal_size.x; + scene_data.screen_size[1] = internal_size.y; - RD::get_singleton()->buffer_update(rb->rbgi.scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); } // Now compute the contents of our buffers. @@ -3726,22 +3825,28 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, push_constant.z_far = p_projections[0].get_z_far(); // these are only used if we have 1 view, else we use the projections in our scene data - push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]); - push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]); - push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0]; - push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1]; + push_constant.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].columns[0][0]); + push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].columns[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[0].columns[0][2]) / p_projections[0].columns[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[0].columns[1][2]) / p_projections[0].columns[1][1]; - bool use_sdfgi = rb->sdfgi != nullptr; + bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI); bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; + Ref<SDFGI> sdfgi; + if (use_sdfgi) { + sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); + } + uint32_t pipeline_specialization = 0; - if (rb->rbgi.using_half_size_gi) { + if (rbgi->using_half_size_gi) { pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES; } if (p_view_count > 1) { pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX; } - if (p_vrs_slices[0].is_valid()) { + bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE); + if (has_vrs_texture) { pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS; } @@ -3751,17 +3856,17 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, push_constant.view_index = v; // setup our uniform set - if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { + if (rbgi->uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) { Vector<RD::Uniform> uniforms; { RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].sdf_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].sdf_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3771,10 +3876,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].light_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3784,10 +3889,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].light_aniso_0_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3797,10 +3902,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].light_aniso_1_tex); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } } uniforms.push_back(u); @@ -3809,10 +3914,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 5; - if (rb->sdfgi) { - u.append_id(rb->sdfgi->occlusion_texture); + if (use_sdfgi) { + u.append_id(sdfgi->occlusion_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } uniforms.push_back(u); } @@ -3835,7 +3940,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(rb->rbgi.ambient_slice[v]); + u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0)); uniforms.push_back(u); } @@ -3843,7 +3948,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; - u.append_id(rb->rbgi.reflection_slice[v]); + u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0)); uniforms.push_back(u); } @@ -3851,10 +3956,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 11; - if (rb->sdfgi) { - u.append_id(rb->sdfgi->lightprobe_texture); + if (use_sdfgi) { + u.append_id(sdfgi->lightprobe_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } uniforms.push_back(u); } @@ -3862,7 +3967,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; - u.append_id(rb->views[v].view_depth); + u.append_id(p_render_buffers->get_depth_texture(v)); uniforms.push_back(u); } { @@ -3876,7 +3981,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 14; - RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(buffer); uniforms.push_back(u); } @@ -3891,7 +3996,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 16; - u.append_id(rb->rbgi.voxel_gi_buffer); + u.append_id(rbgi->get_voxel_gi_buffer()); uniforms.push_back(u); } { @@ -3899,7 +4004,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 17; for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { - u.append_id(rb->rbgi.voxel_gi_textures[i]); + u.append_id(rbgi->voxel_gi_textures[i]); } uniforms.push_back(u); } @@ -3907,29 +4012,29 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 18; - u.append_id(rb->rbgi.scene_data_ubo); + u.append_id(rbgi->scene_data_ubo); uniforms.push_back(u); } - { + if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 19; - RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_VRS); + RID buffer = has_vrs_texture ? p_render_buffers->get_texture_slice(RB_SCOPE_VRS, RB_TEXTURE, v, 0) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS); u.append_id(buffer); uniforms.push_back(u); } - rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); + rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); } RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); - if (rb->rbgi.using_half_size_gi) { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1); + if (rbgi->using_half_size_gi) { + RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x >> 1, internal_size.y >> 1, 1); } else { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x, internal_size.y, 1); } } @@ -3946,25 +4051,31 @@ RID GI::voxel_gi_instance_create(RID p_base) { return rid; } +void GI::voxel_gi_instance_free(RID p_rid) { + GI::VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_rid); + voxel_gi->free_resources(); + voxel_gi_instance_owner.free(p_rid); +} + void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND(!voxel_gi); voxel_gi->transform = p_xform; } bool GI::voxel_gi_needs_update(RID p_probe) const { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND_V(!voxel_gi, false); return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe); } -void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); +void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) { + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND(!voxel_gi); - voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); + voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects); } void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index c9e1a14e2e..651a660f5c 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gi.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* gi.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #ifndef GI_RD_H #define GI_RD_H @@ -44,10 +44,17 @@ #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/storage/utilities.h" +#define RB_SCOPE_GI SNAME("rbgi") +#define RB_SCOPE_SDFGI SNAME("sdfgi") + +#define RB_TEX_AMBIENT SNAME("ambient") +#define RB_TEX_REFLECTION SNAME("reflection") + // Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound struct RenderDataRD; class RendererSceneRenderRD; @@ -76,11 +83,12 @@ public: float dynamic_range = 2.0; float energy = 1.0; + float baked_exposure = 1.0; float bias = 1.4; float normal_bias = 0.0; - float propagation = 0.7; + float propagation = 0.5; bool interior = false; - bool use_two_bounces = false; + bool use_two_bounces = true; uint32_t version = 1; uint32_t data_version = 1; @@ -88,6 +96,60 @@ public: Dependency dependency; }; + /* VOXEL_GI INSTANCE */ + + //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. + + struct VoxelGIInstance { + // access to our containers + GI *gi = nullptr; + + RID probe; + RID texture; + RID write_buffer; + + struct Mipmap { + RID texture; + RID uniform_set; + RID second_bounce_uniform_set; + RID write_uniform_set; + uint32_t level; + uint32_t cell_offset; + uint32_t cell_count; + }; + Vector<Mipmap> mipmaps; + + struct DynamicMap { + RID texture; //color normally, or emission on first pass + RID fb_depth; //actual depth buffer for the first pass, float depth for later passes + RID depth; //actual depth buffer for the first pass, float depth for later passes + RID normal; //normal buffer for the first pass + RID albedo; //emission buffer for the first pass + RID orm; //orm buffer for the first pass + RID fb; //used for rendering, only valid on first map + RID uniform_set; + uint32_t size; + int mipmap; // mipmap to write to, -1 if no mipmap assigned + }; + + Vector<DynamicMap> dynamic_maps; + + int slot = -1; + uint32_t last_probe_version = 0; + uint32_t last_probe_data_version = 0; + + //uint64_t last_pass = 0; + uint32_t render_index = 0; + + bool has_dynamic_object_data = false; + + Transform3D transform; + + void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects); + void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + void free_resources(); + }; + private: static GI *singleton; @@ -97,6 +159,8 @@ private: /* VOXEL_GI INSTANCE */ + mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; + struct VoxelGILight { uint32_t type; float energy; @@ -232,16 +296,13 @@ private: uint32_t max_cascades; int32_t screen_size[2]; - uint32_t use_occlusion; float y_mult; - uint32_t probe_axis_size; float z_near; - float reserved1; - float reserved2; - float cam_transform[16]; - float inv_projection[16]; + float inv_projection[3][4]; + float cam_basis[3][3]; + float cam_origin[3]; }; SdfgiDebugShaderRD debug; @@ -372,9 +433,40 @@ private: public: static GI *get_singleton() { return singleton; } + /* GI */ + + enum { + MAX_VOXEL_GI_INSTANCES = 8 + }; + + // Struct for use in render buffer + class RenderBuffersGI : public RenderBufferCustomDataRD { + GDCLASS(RenderBuffersGI, RenderBufferCustomDataRD) + + private: + RID voxel_gi_buffer; + + public: + RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; + + RID full_buffer; + RID full_dispatch; + RID full_mask; + + /* GI buffers */ + bool using_half_size_gi = false; + + RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; + RID scene_data_ubo; + + RID get_voxel_gi_buffer(); + + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; + virtual void free_data() override; + }; + /* VOXEL GI API */ - VoxelGI *get_voxel_gi(RID p_rid) { return voxel_gi_owner.get_or_null(p_rid); }; bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }; virtual RID voxel_gi_allocate() override; @@ -401,6 +493,9 @@ public: virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) override; virtual float voxel_gi_get_energy(RID p_voxel_gi) const override; + virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) override; + virtual float voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const override; + virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) override; virtual float voxel_gi_get_bias(RID p_voxel_gi) const override; @@ -421,76 +516,37 @@ public: RID voxel_gi_get_sdf_texture(RID p_voxel_gi); - /* VOXEL_GI INSTANCE */ - - //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. - - struct VoxelGIInstance { - // access to our containers - GI *gi = nullptr; - - RID probe; - RID texture; - RID write_buffer; - - struct Mipmap { - RID texture; - RID uniform_set; - RID second_bounce_uniform_set; - RID write_uniform_set; - uint32_t level; - uint32_t cell_offset; - uint32_t cell_count; - }; - Vector<Mipmap> mipmaps; + Dependency *voxel_gi_get_dependency(RID p_voxel_gi) const; - struct DynamicMap { - RID texture; //color normally, or emission on first pass - RID fb_depth; //actual depth buffer for the first pass, float depth for later passes - RID depth; //actual depth buffer for the first pass, float depth for later passes - RID normal; //normal buffer for the first pass - RID albedo; //emission buffer for the first pass - RID orm; //orm buffer for the first pass - RID fb; //used for rendering, only valid on first map - RID uniform_set; - uint32_t size; - int mipmap; // mipmap to write to, -1 if no mipmap assigned - }; - - Vector<DynamicMap> dynamic_maps; - - int slot = -1; - uint32_t last_probe_version = 0; - uint32_t last_probe_data_version = 0; - - //uint64_t last_pass = 0; - uint32_t render_index = 0; - - bool has_dynamic_object_data = false; - - Transform3D transform; + /* VOXEL_GI INSTANCE */ - void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); - void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + _FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) { + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); + ERR_FAIL_COND_V(!voxel_gi, RID()); + return voxel_gi->texture; }; - mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; + _FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) { + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); + ERR_FAIL_NULL(voxel_gi); - _FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const { - return voxel_gi_instance_owner.get_or_null(p_probe); + voxel_gi->render_index = p_index; }; - _FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); - ERR_FAIL_COND_V(!voxel_gi, RID()); - return voxel_gi->texture; - }; + bool voxel_gi_instance_owns(RID p_rid) const { + return voxel_gi_instance_owner.owns(p_rid); + } + + void voxel_gi_instance_free(RID p_rid); RS::VoxelGIQuality voxel_gi_quality = RS::VOXEL_GI_QUALITY_LOW; /* SDFGI */ - struct SDFGI { + class SDFGI : public RenderBufferCustomDataRD { + GDCLASS(SDFGI, RenderBufferCustomDataRD) + + public: enum { MAX_CASCADES = 8, CASCADE_SIZE = 128, @@ -508,6 +564,7 @@ public: float to_cell; int32_t probe_offset[3]; uint32_t pad; + float pad2[4]; }; //cascade blocks are full-size for volume (128^3), half size for albedo/emission @@ -547,6 +604,8 @@ public: RID integrate_uniform_set; RID lights_buffer; + float baked_exposure_normalization = 1.0; + bool all_dynamic_lights_dirty = true; }; @@ -613,8 +672,11 @@ public: int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically RID integrate_sky_uniform_set; + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; + virtual void free_data() override; + ~SDFGI(); + void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi); - void erase(); void update(RID p_env, const Vector3 &p_world_position); void update_light(); void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky); @@ -625,9 +687,9 @@ public: void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views); void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); - void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render); - void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render); - void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render); + void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data); + void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization); + void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result); }; RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16; @@ -644,34 +706,6 @@ public: int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; } - /* GI */ - enum { - MAX_VOXEL_GI_INSTANCES = 8 - }; - - // Struct for use in render buffer - struct RenderBuffersGI { - RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; - RID voxel_gi_buffer; - - RID full_buffer; - RID full_dispatch; - RID full_mask; - - /* GI buffers */ - RID ambient_buffer; - RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS]; - RID reflection_buffer; - RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS]; - bool using_half_size_gi = false; - uint32_t view_count = 1; - - RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; - RID scene_data_ubo; - - void free(); - }; - struct SDFGIData { float grid_size[3]; uint32_t max_cascades; @@ -701,6 +735,8 @@ public: float to_probe; // 1/bounds * grid_size int32_t probe_world_offset[3]; float to_cell; // 1/bounds * grid_size + float pad[3]; + float exposure_normalization; }; ProbeCascadeData cascades[SDFGI::MAX_CASCADES]; @@ -716,6 +752,9 @@ public: float normal_bias; // 4 - 88 uint32_t blend_ambient; // 4 - 92 uint32_t mipmaps; // 4 - 96 + + float pad[3]; // 12 - 108 + float exposure_normalization; // 4 - 112 }; struct SceneData { @@ -771,15 +810,15 @@ public: void init(RendererRD::SkyRD *p_sky); void free(); - SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); + Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); - void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); - void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); + void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used); + void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances); RID voxel_gi_instance_create(RID p_base); void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); bool voxel_gi_needs_update(RID p_probe) const; - void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); + void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects); void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index 228d2673f2..7e02f98ce9 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1,53 +1,56 @@ -/*************************************************************************/ -/* sky.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* sky.cpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #include "sky.h" #include "core/config/project_settings.h" #include "core/math/math_defs.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" +#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" #include "servers/rendering/rendering_server_default.h" #include "servers/rendering/rendering_server_globals.h" using namespace RendererRD; +#define RB_SCOPE_SKY SNAME("sky_buffers") +#define RB_HALF_TEXTURE SNAME("half_texture") +#define RB_QUARTER_TEXTURE SNAME("quarter_texture") + //////////////////////////////////////////////////////////////////////////////// // SKY SHADER -void SkyRD::SkyShaderData::set_path_hint(const String &p_path) { - path = p_path; -} - void SkyRD::SkyShaderData::set_code(const String &p_code) { //compile @@ -114,12 +117,16 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) { for (int i = 0; i < gen_code.defines.size(); i++) { print_line(gen_code.defines[i]); } + + HashMap<String, String>::Iterator el = gen_code.code.begin(); + while (el) { + print_line("\n**code " + el->key + ":\n" + el->value); + ++el; + } + print_line("\n**uniforms:\n" + gen_code.uniforms); - // print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - // print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); + print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]); + print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]); #endif scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines); @@ -147,82 +154,6 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { - if (!p_texture.is_valid()) { - if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { - default_texture_params[p_name].erase(p_index); - - if (default_texture_params[p_name].is_empty()) { - default_texture_params.erase(p_name); - } - } - } else { - if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = HashMap<int, RID>(); - } - default_texture_params[p_name][p_index] = p_texture; - } -} - -void SkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - HashMap<int, StringName> order; - - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - if (E.value.texture_order >= 0) { - order[E.value.texture_order + 100000] = E.key; - } else { - order[E.value.order] = E.key; - } - } - String last_group; - for (const KeyValue<int, StringName> &E : order) { - String group = uniforms[E.value].group; - if (!uniforms[E.value].subgroup.is_empty()) { - group += "::" + uniforms[E.value].subgroup; - } - - if (group != last_group) { - PropertyInfo pi; - pi.usage = PROPERTY_USAGE_GROUP; - pi.name = group; - p_param_list->push_back(pi); - - last_group = group; - } - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); - pi.name = E.value; - p_param_list->push_back(pi); - } -} - -void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { - if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { - continue; - } - - RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E.value); - p.info.name = E.key; //supply name - p.index = E.value.instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); - p_param_list->push_back(p); - } -} - -bool SkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - bool SkyRD::SkyShaderData::is_animated() const { return false; } @@ -231,15 +162,6 @@ bool SkyRD::SkyShaderData::casts_shadows() const { return false; } -Variant SkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint); - } - return Variant(); -} - RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); @@ -263,7 +185,7 @@ bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant uniform_set_updated = true; - return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); + return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL, true); } SkyRD::SkyMaterialData::~SkyMaterialData() { @@ -288,22 +210,20 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar p_array[11] = 0; } -void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) { +void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) { SkyPushConstant sky_push_constant; memset(&sky_push_constant, 0, sizeof(SkyPushConstant)); - for (uint32_t v = 0; v < p_view_count; v++) { - // We only need key components of our projection matrix - sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0]; - sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0]; - sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1]; - sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1]; - } + // We only need key components of our projection matrix + sky_push_constant.projection[0] = p_projection.columns[2][0]; + sky_push_constant.projection[1] = p_projection.columns[0][0]; + sky_push_constant.projection[2] = p_projection.columns[2][1]; + sky_push_constant.projection[3] = p_projection.columns[1][1]; + sky_push_constant.position[0] = p_position.x; sky_push_constant.position[1] = p_position.y; sky_push_constant.position[2] = p_position.z; - sky_push_constant.multiplier = p_multiplier; sky_push_constant.time = p_time; sky_push_constant.luminance_multiplier = p_luminance_multiplier; store_transform_3x3(p_orientation, sky_push_constant.orientation); @@ -357,7 +277,7 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo uint32_t w = p_size, h = p_size; EffectsRD *effects = RendererCompositorRD::singleton->get_effects(); - ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised"); + ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialized"); bool prefer_raster_effects = effects->get_prefer_raster_effects(); if (p_use_array) { @@ -461,7 +381,7 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); - ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); + ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); if (prefer_raster_effects) { @@ -519,7 +439,7 @@ void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) { void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); - ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); + ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); if (prefer_raster_effects) { @@ -588,7 +508,7 @@ void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_array void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) { RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); - ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); + ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized"); bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); RD::get_singleton()->draw_command_begin_label("Update Radiance Cubemap Array Mipmaps"); @@ -625,28 +545,15 @@ void SkyRD::Sky::free() { uniform_buffer = RID(); } - if (half_res_pass.is_valid()) { - RD::get_singleton()->free(half_res_pass); - half_res_pass = RID(); - } - - if (quarter_res_pass.is_valid()) { - RD::get_singleton()->free(quarter_res_pass); - quarter_res_pass = RID(); - } - if (material.is_valid()) { RSG::material_storage->material_free(material); material = RID(); } } -RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) { +RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { - return texture_uniform_sets[p_version]; - } Vector<RD::Uniform> uniforms; { RD::Uniform u; @@ -655,7 +562,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { u.append_id(radiance); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } uniforms.push_back(u); } @@ -663,17 +570,18 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; // half res - if (half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { - if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { u.append_id(reflection.layers[0].views[1]); } else { - u.append_id(half_res_pass); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } else { - if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + RID half_texture = p_render_buffers->has_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE) ? p_render_buffers->get_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE) : RID(); + if (half_texture.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES) { + u.append_id(half_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } } uniforms.push_back(u); @@ -682,24 +590,24 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; // quarter res - if (quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { - if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + if (reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { u.append_id(reflection.layers[0].views[2]); } else { - u.append_id(quarter_res_pass); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); } } else { - if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + RID quarter_texture = p_render_buffers->has_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE) ? p_render_buffers->get_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE) : RID(); + if (quarter_texture.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES) { + u.append_id(quarter_texture); } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); } } uniforms.push_back(u); } - texture_uniform_sets[p_version] = RD::get_singleton()->uniform_set_create(uniforms, p_default_shader_rd, SKY_SET_TEXTURES); - return texture_uniform_sets[p_version]; + return UniformSetCacheRD::get_singleton()->get_cache_vec(p_default_shader_rd, SKY_SET_TEXTURES, uniforms); } bool SkyRD::Sky::set_radiance_size(int p_radiance_size) { @@ -758,7 +666,7 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; // Could be RGBA16 tf.width = p_size.width; tf.height = p_size.height; tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; @@ -768,9 +676,7 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0); RD::get_singleton()->free(rad_tex); - Ref<Image> img; - img.instantiate(); - img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data); + Ref<Image> img = Image::create_from_data(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data); for (int i = 0; i < p_size.width; i++) { for (int j = 0; j < p_size.height; j++) { Color c = img->get_pixel(i, j); @@ -789,24 +695,24 @@ Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, con //////////////////////////////////////////////////////////////////////////////// // SkyRD -RendererRD::ShaderData *SkyRD::_create_sky_shader_func() { +RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() { SkyShaderData *shader_data = memnew(SkyShaderData); return shader_data; } -RendererRD::ShaderData *SkyRD::_create_sky_shader_funcs() { +RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() { // !BAS! Why isn't _create_sky_shader_func not just static too? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func(); }; -RendererRD::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) { SkyMaterialData *material_data = memnew(SkyMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; } -RendererRD::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) { +RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) { // !BAS! same here, we could just make _create_sky_material_func static? return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader)); }; @@ -855,8 +761,8 @@ void SkyRD::init() { } // register our shader funds - material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); - material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs); + material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_shader_funcs); + material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_material_funcs); { ShaderCompiler::DefaultIdentifierActions actions; @@ -864,7 +770,7 @@ void SkyRD::init() { actions.renames["COLOR"] = "color"; actions.renames["ALPHA"] = "alpha"; actions.renames["EYEDIR"] = "cube_normal"; - actions.renames["POSITION"] = "params.position_multiplier.xyz"; + actions.renames["POSITION"] = "params.position"; actions.renames["SKY_COORDS"] = "panorama_coords"; actions.renames["SCREEN_UV"] = "uv"; actions.renames["FRAGCOORD"] = "gl_FragCoord"; @@ -903,6 +809,7 @@ void SkyRD::init() { actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n"; actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n"; actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; + actions.render_mode_defines["use_debanding"] = "#define USE_DEBANDING\n"; actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; @@ -937,7 +844,7 @@ void sky() { material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO)); @@ -999,7 +906,7 @@ void sky() { RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); + RID vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); u.append_id(vfog); uniforms.push_back(u); } @@ -1033,21 +940,21 @@ void sky() { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 1; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 2; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE)); + u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE)); uniforms.push_back(u); } @@ -1080,7 +987,7 @@ SkyRD::~SkyRD() { // cleanup anything created in init... RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY)); + SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); sky_shader.shader.version_free(md->shader_data->version); RD::get_singleton()->free(sky_scene_state.directional_light_buffer); RD::get_singleton()->free(sky_scene_state.uniform_buffer); @@ -1106,11 +1013,17 @@ SkyRD::~SkyRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency } -void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); + ERR_FAIL_COND(p_render_buffers.is_null()); + + // make sure we support our view count + ERR_FAIL_COND(p_view_count == 0); + ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); + SkyMaterialData *material = nullptr; Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); @@ -1122,7 +1035,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1130,7 +1043,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1139,31 +1052,14 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh ERR_FAIL_COND(!shader_data); - // Invalidate supbass buffers if screen size changes - if (sky->screen_size != p_screen_size) { - sky->screen_size = p_screen_size; - sky->screen_size.x = sky->screen_size.x < 4 ? 4 : sky->screen_size.x; - sky->screen_size.y = sky->screen_size.y < 4 ? 4 : sky->screen_size.y; - if (shader_data->uses_half_res) { - if (sky->half_res_pass.is_valid()) { - RD::get_singleton()->free(sky->half_res_pass); - sky->half_res_pass = RID(); - } - invalidate_sky(sky); - } - if (shader_data->uses_quarter_res) { - if (sky->quarter_res_pass.is_valid()) { - RD::get_singleton()->free(sky->quarter_res_pass); - sky->quarter_res_pass = RID(); - } - invalidate_sky(sky); - } - } + material->set_as_used(); + + // Save our screen size, our buffers will already have been cleared + sky->screen_size.x = p_screen_size.x < 4 ? 4 : p_screen_size.x; + sky->screen_size.y = p_screen_size.y < 4 ? 4 : p_screen_size.y; - // Create new subpass buffers if necessary - if ((shader_data->uses_half_res && sky->half_res_pass.is_null()) || - (shader_data->uses_quarter_res && sky->quarter_res_pass.is_null()) || - sky->radiance.is_null()) { + // Trigger updating radiance buffers + if (sky->radiance.is_null()) { invalidate_sky(sky); update_dirty_skys(); } @@ -1184,29 +1080,28 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh sky->reflection.dirty = true; } - if (!p_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) { - sky->prev_position = p_transform.origin; + if (!p_cam_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) { + sky->prev_position = p_cam_transform.origin; sky->reflection.dirty = true; } + sky_scene_state.ubo.directional_light_count = 0; if (shader_data->uses_light) { - sky_scene_state.ubo.directional_light_count = 0; // Run through the list of lights in the scene and pick out the Directional Lights. // This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called // after the depth prepass, but this runs before the depth prepass for (int i = 0; i < (int)p_lights.size(); i++) { - RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_lights[i]); - if (!li) { + if (!light_storage->owns_light_instance(p_lights[i])) { continue; } - RID base = li->light; + RID base = light_storage->light_instance_get_base_light(p_lights[i]); ERR_CONTINUE(base.is_null()); RS::LightType type = light_storage->light_get_type(base); if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) { SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count]; - Transform3D light_transform = li->transform; + Transform3D light_transform = light_storage->light_instance_get_base_transform(p_lights[i]); Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); sky_light_data.direction[0] = world_direction.x; @@ -1216,6 +1111,14 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh float sign = light_storage->light_is_negative(base) ? -1 : 1; sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY); + if (p_scene_render->is_using_physical_light_units()) { + sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY); + } + + if (p_camera_attributes.is_valid()) { + sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes); + } + Color linear_col = light_storage->light_get_color(base).srgb_to_linear(); sky_light_data.color[0] = linear_col.r; sky_light_data.color[1] = linear_col.g; @@ -1228,7 +1131,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh // I know tan(0) is 0, but let's not risk it with numerical precision. // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); } else { angular_diameter = 0.0; } @@ -1248,6 +1151,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh light_data_dirty = true; for (uint32_t i = sky_scene_state.ubo.directional_light_count; i < sky_scene_state.max_directional_lights; i++) { sky_scene_state.directional_lights[i].enabled = false; + sky_scene_state.last_frame_directional_lights[i].enabled = false; } } @@ -1283,28 +1187,42 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh //setup fog variables sky_scene_state.ubo.volumetric_fog_enabled = false; if (p_render_buffers.is_valid()) { - if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) { + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); sky_scene_state.ubo.volumetric_fog_enabled = true; - float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers); + float fog_end = fog->length; if (fog_end > 0.0) { sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end; } else { sky_scene_state.ubo.volumetric_fog_inv_length = 1.0; } - float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup + float fog_detail_spread = fog->spread; //reverse lookup if (fog_detail_spread > 0.0) { sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread; } else { sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0; } - sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers); + sky_scene_state.fog_uniform_set = fog->sky_uniform_set; } } - sky_scene_state.ubo.z_far = p_projection.get_z_far(); + sky_scene_state.view_count = p_view_count; + sky_scene_state.cam_transform = p_cam_transform; + sky_scene_state.cam_projection = p_view_projections[0]; // We only use this when rendering a single view + + // Our info in our UBO is only used if we're rendering stereo + for (uint32_t i = 0; i < p_view_count; i++) { + RendererRD::MaterialStorage::store_camera(p_view_projections[i].inverse(), sky_scene_state.ubo.view_inv_projections[i]); + sky_scene_state.ubo.view_eye_offsets[i][0] = p_view_eye_offsets[i].x; + sky_scene_state.ubo.view_eye_offsets[i][1] = p_view_eye_offsets[i].y; + sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z; + sky_scene_state.ubo.view_eye_offsets[i][3] = 0.0; + } + + sky_scene_state.ubo.z_far = p_view_projections[0].get_z_far(); // Should be the same for all projection sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env); sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env); sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env); @@ -1315,10 +1233,14 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env); + sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_env); + sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_env); + RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo); } -void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier) { + ERR_FAIL_COND(p_render_buffers.is_null()); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); @@ -1330,7 +1252,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D SkyMaterialData *material = nullptr; if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1338,7 +1260,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); @@ -1347,8 +1269,6 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D ERR_FAIL_COND(!shader_data); - float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); - bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY; RS::SkyMode sky_mode = sky->mode; @@ -1398,6 +1318,8 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D correction.set_depth_correction(true); cm = correction * cm; + // Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader. + if (shader_data->uses_quarter_res) { RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap"); PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; @@ -1408,10 +1330,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd, p_render_buffers); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1427,10 +1349,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd, p_render_buffers); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1442,10 +1364,10 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap"); for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd, p_render_buffers); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); + _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } RD::get_singleton()->draw_command_end_label(); @@ -1471,7 +1393,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D } sky->processing_layer = 1; } - + sky->baked_exposure = p_luminance_multiplier; sky->reflection.dirty = false; } else { @@ -1487,13 +1409,11 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D } } -void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time) { +void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier) { + ERR_FAIL_COND(p_render_buffers.is_null()); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); - ERR_FAIL_COND(p_view_count == 0); - ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); SkyMaterialData *material = nullptr; @@ -1506,7 +1426,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1514,178 +1434,94 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); SkyShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); - Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); - sky_transform.invert(); - - float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); - float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); - - // Camera - Projection camera; - uint32_t view_count = p_view_count; - const Projection *projections = p_projections; - - if (custom_fov) { - // With custom fov we don't support stereo... - float near_plane = p_projections[0].get_z_near(); - float far_plane = p_projections[0].get_z_far(); - float aspect = p_projections[0].get_aspect(); - - camera.set_perspective(custom_fov, aspect, near_plane, far_plane); - - view_count = 1; - projections = &camera; - } - - sky_transform = sky_transform * p_transform.basis; - - if (shader_data->uses_quarter_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; - - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); - - Vector<Color> clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); - RD::get_singleton()->draw_list_end(); - } - - if (shader_data->uses_half_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; - - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); - - Vector<Color> clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); - RD::get_singleton()->draw_list_end(); - } - - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND]; - - RID texture_uniform_set; - if (sky) { - texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); - } else { - texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set; - } - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0); - RD::get_singleton()->draw_list_end(); -} - -void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - ERR_FAIL_COND(p_env.is_null()); - - ERR_FAIL_COND(p_view_count == 0); - ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - - Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); - ERR_FAIL_COND(!sky); - - SkyMaterialData *material = nullptr; - RID sky_material; - - sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); - - if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); - if (!material || !material->shader_data->valid) { - material = nullptr; - } + if (!shader_data->uses_quarter_res && !shader_data->uses_half_res) { + return; } - if (!material) { - sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); - } - - ERR_FAIL_COND(!material); + material->set_as_used(); - SkyShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); + RENDER_TIMESTAMP("Setup Sky Resolution Buffers"); + RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers"); Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); sky_transform.invert(); - float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); // Camera - Projection camera; - uint32_t view_count = p_view_count; - const Projection *projections = p_projections; + Projection projection = sky_scene_state.cam_projection; - if (custom_fov) { + if (custom_fov && sky_scene_state.view_count == 1) { // With custom fov we don't support stereo... - float near_plane = p_projections[0].get_z_near(); - float far_plane = p_projections[0].get_z_far(); - float aspect = p_projections[0].get_aspect(); + float near_plane = projection.get_z_near(); + float far_plane = projection.get_z_far(); + float aspect = projection.get_aspect(); - camera.set_perspective(custom_fov, aspect, near_plane, far_plane); - - view_count = 1; - projections = &camera; + projection.set_perspective(custom_fov, aspect, near_plane, far_plane); } - sky_transform = p_transform.basis * sky_transform; + sky_transform = sky_transform * sky_scene_state.cam_transform.basis; if (shader_data->uses_quarter_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; + + // Grab texture and framebuffer from cache, create if needed... + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + Size2i quarter_size = sky->screen_size / 4; + RID texture = p_render_buffers->create_texture(RB_SCOPE_SKY, RB_QUARTER_TEXTURE, texture_format, usage_bits, RD::TEXTURE_SAMPLES_1, quarter_size); + RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache_multiview(sky_scene_state.view_count, texture); - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd, p_render_buffers); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } if (shader_data->uses_half_res) { - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; + PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; - RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); + // Grab texture and framebuffer from cache, create if needed... + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + Size2i half_size = sky->screen_size / 2; + RID texture = p_render_buffers->create_texture(RB_SCOPE_SKY, RB_HALF_TEXTURE, texture_format, usage_bits, RD::TEXTURE_SAMPLES_1, half_size); + RID framebuffer = FramebufferCacheRD::get_singleton()->get_cache_multiview(sky_scene_state.view_count, texture); + + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd, p_render_buffers); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + _render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); RD::get_singleton()->draw_list_end(); } + + RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } -void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) { +void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier) { + ERR_FAIL_COND(p_render_buffers.is_null()); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); - ERR_FAIL_COND(p_view_count == 0); - ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS); - Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); SkyMaterialData *material = nullptr; @@ -1698,7 +1534,7 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env)); if (sky_material.is_valid()) { - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); if (!material || !material->shader_data->valid) { material = nullptr; } @@ -1706,56 +1542,51 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie if (!material) { sky_material = sky_shader.default_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } } if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) { sky_material = sky_scene_state.fog_material; - material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY)); + material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY)); } ERR_FAIL_COND(!material); SkyShaderData *shader_data = material->shader_data; - ERR_FAIL_COND(!shader_data); + material->set_as_used(); + Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env); sky_transform.invert(); - float multiplier = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy(p_env); float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env); // Camera - Projection camera; - uint32_t view_count = p_view_count; - const Projection *projections = p_projections; + Projection projection = sky_scene_state.cam_projection; - if (custom_fov) { + if (custom_fov && sky_scene_state.view_count == 1) { // With custom fov we don't support stereo... - float near_plane = p_projections[0].get_z_near(); - float far_plane = p_projections[0].get_z_far(); - float aspect = p_projections[0].get_aspect(); - - camera.set_perspective(custom_fov, aspect, near_plane, far_plane); + float near_plane = projection.get_z_near(); + float far_plane = projection.get_z_far(); + float aspect = projection.get_aspect(); - view_count = 1; - projections = &camera; + projection.set_perspective(custom_fov, aspect, near_plane, far_plane); } - sky_transform = p_transform.basis * sky_transform; + sky_transform = sky_transform * sky_scene_state.cam_transform.basis; - PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND]; + PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND]; RID texture_uniform_set; if (sky) { - texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); + texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd, p_render_buffers); } else { texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set; } - _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier); + _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier); } void SkyRD::invalidate_sky(Sky *p_sky) { @@ -1770,9 +1601,11 @@ void SkyRD::update_dirty_skys() { Sky *sky = dirty_sky_list; while (sky) { - bool texture_set_dirty = false; //update sky configuration if texture is missing + // TODO See if we can move this into `update_radiance_buffers` and remove our dirty_sky logic. + // As this is basically a duplicate of the logic in reflection probes we could move this logic + // into RenderSceneBuffersRD and use that from both places. if (sky->radiance.is_null()) { int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1; @@ -1815,47 +1648,6 @@ void SkyRD::update_dirty_skys() { sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format); } - texture_set_dirty = true; - } - - // Create subpass buffers if they haven't been created already - if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { - RD::TextureFormat tformat; - tformat.format = texture_format; - tformat.width = sky->screen_size.x / 2; - tformat.height = sky->screen_size.y / 2; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D; - - sky->half_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); - Vector<RID> texs; - texs.push_back(sky->half_res_pass); - sky->half_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); - texture_set_dirty = true; - } - - if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { - RD::TextureFormat tformat; - tformat.format = texture_format; - tformat.width = sky->screen_size.x / 4; - tformat.height = sky->screen_size.y / 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.texture_type = RD::TEXTURE_TYPE_2D; - - sky->quarter_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); - Vector<RID> texs; - texs.push_back(sky->quarter_res_pass); - sky->quarter_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); - texture_set_dirty = true; - } - - if (texture_set_dirty) { - for (int i = 0; i < SKY_TEXTURE_SET_MAX; i++) { - if (sky->texture_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(sky->texture_uniform_sets[i])) { - RD::get_singleton()->free(sky->texture_uniform_sets[i]); - sky->texture_uniform_sets[i] = RID(); - } - } } sky->reflection.dirty = true; @@ -1877,6 +1669,13 @@ RID SkyRD::sky_get_material(RID p_sky) const { return sky->material; } +float SkyRD::sky_get_baked_exposure(RID p_sky) const { + Sky *sky = get_sky(p_sky); + ERR_FAIL_COND_V(!sky, 1.0); + + return sky->baked_exposure; +} + RID SkyRD::allocate_sky_rid() { return sky_owner.allocate_rid(); } diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index 5402705918..4ace59dfa5 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* sky.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ +/**************************************************************************/ +/* sky.h */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ #ifndef SKY_RD_H #define SKY_RD_H @@ -42,6 +42,7 @@ // Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound class RendererSceneRenderRD; +class RenderSceneBuffersRD; namespace RendererRD { @@ -98,29 +99,25 @@ private: struct SkyPushConstant { float orientation[12]; // 48 - 48 - float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80 - float position[3]; // 12 - 92 - float multiplier; // 4 - 96 - float time; // 4 - 100 - float luminance_multiplier; // 4 - 104 - float pad[2]; // 8 - 112 // Using pad to align on 16 bytes + float projection[4]; // 16 - 64 + float position[3]; // 12 - 76 + float time; // 4 - 80 + float pad[3]; // 12 - 92 + float luminance_multiplier; // 4 - 96 // 128 is the max size of a push constant. We can replace "pad" but we can't add any more. }; - struct SkyShaderData : public RendererRD::ShaderData { + struct SkyShaderData : public RendererRD::MaterialStorage::ShaderData { bool valid = false; RID version; PipelineCacheRD pipelines[SKY_VERSION_MAX]; - HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; - String path; String code; - HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; bool uses_position = false; @@ -129,43 +126,47 @@ private: bool uses_light = false; virtual void set_code(const String &p_Code); - virtual void set_path_hint(const String &p_hint); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); - virtual void get_param_list(List<PropertyInfo> *p_param_list) const; - virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; virtual RS::ShaderNativeSourceCode get_native_source_code() const; SkyShaderData() {} virtual ~SkyShaderData(); }; - void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier); + void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier); public: struct SkySceneState { struct UBO { - uint32_t volumetric_fog_enabled; - float volumetric_fog_inv_length; - float volumetric_fog_detail_spread; - - float fog_aerial_perspective; - - float fog_light_color[3]; - float fog_sun_scatter; - - uint32_t fog_enabled; - float fog_density; - - float z_far; - uint32_t directional_light_count; + float view_inv_projections[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128 + float view_eye_offsets[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 160 + + uint32_t volumetric_fog_enabled; // 4 - 164 + float volumetric_fog_inv_length; // 4 - 168 + float volumetric_fog_detail_spread; // 4 - 172 + float volumetric_fog_sky_affect; // 4 - 176 + + uint32_t fog_enabled; // 4 - 180 + float fog_sky_affect; // 4 - 184 + float fog_density; // 4 - 188 + float fog_sun_scatter; // 4 - 192 + + float fog_light_color[3]; // 12 - 204 + float fog_aerial_perspective; // 4 - 208 + + float z_far; // 4 - 212 + uint32_t directional_light_count; // 4 - 216 + uint32_t pad1; // 4 - 220 + uint32_t pad2; // 4 - 224 }; UBO ubo; + uint32_t view_count = 1; + Transform3D cam_transform; + Projection cam_projection; + SkyDirectionalLightData *directional_lights = nullptr; SkyDirectionalLightData *last_frame_directional_lights = nullptr; uint32_t max_directional_lights; @@ -231,7 +232,7 @@ public: RID default_shader_rd; } sky_shader; - struct SkyMaterialData : public RendererRD::MaterialData { + struct SkyMaterialData : public RendererRD::MaterialStorage::MaterialData { SkyShaderData *shader_data = nullptr; RID uniform_set; bool uniform_set_updated; @@ -244,13 +245,10 @@ public: struct Sky { RID radiance; - RID half_res_pass; - RID half_res_framebuffer; RID quarter_res_pass; RID quarter_res_framebuffer; Size2i screen_size; - RID texture_uniform_sets[SKY_TEXTURE_SET_MAX]; RID uniform_set; RID material; @@ -264,6 +262,7 @@ public: bool dirty = false; int processing_layer = 0; Sky *dirty_list = nullptr; + float baked_exposure = 1.0; //State to track when radiance cubemap needs updating SkyMaterialData *prev_material = nullptr; @@ -272,7 +271,7 @@ public: void free(); - RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd); + RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers); bool set_radiance_size(int p_radiance_size); bool set_mode(RS::SkyMode p_mode); bool set_material(RID p_material); @@ -285,27 +284,28 @@ public: mutable RID_Owner<Sky, true> sky_owner; int roughness_layers; - RendererRD::ShaderData *_create_sky_shader_func(); - static RendererRD::ShaderData *_create_sky_shader_funcs(); + RendererRD::MaterialStorage::ShaderData *_create_sky_shader_func(); + static RendererRD::MaterialStorage::ShaderData *_create_sky_shader_funcs(); - RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); - static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader); + RendererRD::MaterialStorage::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); + static RendererRD::MaterialStorage::MaterialData *_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader); SkyRD(); void init(); void set_texture_format(RD::DataFormat p_texture_format); ~SkyRD(); - void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); - void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer - void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); - void draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); + void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0); + void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0); + void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0); void invalidate_sky(Sky *p_sky); void update_dirty_skys(); RID sky_get_material(RID p_sky) const; + RID sky_get_radiance_texture_rd(RID p_sky) const; + float sky_get_baked_exposure(RID p_sky) const; RID allocate_sky_rid(); void initialize_sky_rid(RID p_rid); @@ -315,8 +315,6 @@ public: void sky_set_mode(RID p_sky, RS::SkyMode p_mode); void sky_set_material(RID p_sky, RID p_material); Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size); - - RID sky_get_radiance_texture_rd(RID p_sky) const; }; } // namespace RendererRD |