summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd/environment/gi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd/environment/gi.cpp')
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp910
1 files changed, 516 insertions, 394 deletions
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index f3be4a7085..08133bf8d6 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -1,40 +1,40 @@
-/*************************************************************************/
-/* 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"
#include "core/config/project_settings.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/renderer_storage_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"
@@ -110,6 +110,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
Vector<Vector<uint8_t>> s;
s.push_back(p_distance_field);
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
+ RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
}
#if 0
{
@@ -123,6 +124,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM);
tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT);
voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
}
RID shared_tex;
{
@@ -184,7 +186,7 @@ void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xfo
voxel_gi->version++;
voxel_gi->data_version++;
- voxel_gi->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ voxel_gi->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
AABB GI::voxel_gi_get_bounds(RID p_voxel_gi) const {
@@ -286,43 +288,43 @@ float GI::voxel_gi_get_energy(RID p_voxel_gi) const {
return voxel_gi->energy;
}
-void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
+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->bias = p_bias;
+ voxel_gi->baked_exposure = p_baked_exposure;
}
-float GI::voxel_gi_get_bias(RID p_voxel_gi) const {
+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->bias;
+ return voxel_gi->baked_exposure;
}
-void GI::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) {
+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);
- voxel_gi->normal_bias = p_normal_bias;
+ voxel_gi->bias = p_bias;
}
-float GI::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
+float GI::voxel_gi_get_bias(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->normal_bias;
+ return voxel_gi->bias;
}
-void GI::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) {
+void GI::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) {
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
- voxel_gi->anisotropy_strength = p_strength;
+ voxel_gi->normal_bias = p_normal_bias;
}
-float GI::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const {
+float GI::voxel_gi_get_normal_bias(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->anisotropy_strength;
+ return voxel_gi->normal_bias;
}
void GI::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
@@ -383,19 +385,25 @@ 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
-void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) {
+void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_gi->storage;
gi = p_gi;
- num_cascades = p_env->sdfgi_cascades;
- min_cell_size = p_env->sdfgi_min_cell_size;
- uses_occlusion = p_env->sdfgi_use_occlusion;
- y_scale_mode = p_env->sdfgi_y_scale;
+ num_cascades = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_cascades(p_env);
+ min_cell_size = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_min_cell_size(p_env);
+ uses_occlusion = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_use_occlusion(p_env);
+ y_scale_mode = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_y_scale(p_env);
static const float y_scale[3] = { 2.0, 1.5, 1.0 };
y_mult = y_scale[y_scale_mode];
cascades.resize(num_cascades);
@@ -417,29 +425,38 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
RD::TextureFormat tf_render = tf_sdf;
tf_render.format = RD::DATA_FORMAT_R16_UINT;
render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo");
tf_render.format = RD::DATA_FORMAT_R32_UINT;
render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission");
render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso");
tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
for (int i = 0; i < 8; i++) {
render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i));
}
tf_render.format = RD::DATA_FORMAT_R32_UINT;
render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing");
tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0");
render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1");
tf_render.width /= 2;
tf_render.height /= 2;
tf_render.depth /= 2;
render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0");
render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1");
}
RD::TextureFormat tf_occlusion = tf_sdf;
@@ -480,7 +497,9 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll");
lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll");
{
//octahedral lightprobes
@@ -494,6 +513,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
//lightprobe texture is an octahedral texture
lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data");
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data);
@@ -507,28 +527,32 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
//lightprobe texture is an octahedral texture
ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
+ RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture");
}
cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
+ RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data");
{
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
occlusion_texture = RD::get_singleton()->texture_create_shared(tv, occlusion_data);
}
- for (uint32_t i = 0; i < cascades.size(); i++) {
- SDFGI::Cascade &cascade = cascades[i];
-
+ for (SDFGI::Cascade &cascade : cascades) {
/* 3D Textures */
cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture");
cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data");
cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture");
cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture");
{
RD::TextureView tv;
@@ -555,9 +579,11 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
/* Probe History */
cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
/* Buffers */
@@ -715,9 +741,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
}
//direct light
- for (uint32_t i = 0; i < cascades.size(); i++) {
- SDFGI::Cascade &cascade = cascades[i];
-
+ for (SDFGI::Cascade &cascade : cascades) {
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
@@ -727,7 +751,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
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);
@@ -803,7 +827,8 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
uniforms.push_back(u);
}
- cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, 0), 0);
+ cascade.sdf_direct_light_static_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_STATIC), 0);
+ cascade.sdf_direct_light_dynamic_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC), 0);
}
//preprocess initialize uniform set
@@ -970,7 +995,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
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);
@@ -983,7 +1008,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
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);
@@ -996,7 +1021,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
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);
@@ -1009,7 +1034,7 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
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);
@@ -1093,16 +1118,19 @@ void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world
cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 0);
}
- bounce_feedback = p_env->sdfgi_bounce_feedback;
- energy = p_env->sdfgi_energy;
- normal_bias = p_env->sdfgi_normal_bias;
- probe_bias = p_env->sdfgi_probe_bias;
- reads_sky = p_env->sdfgi_read_sky_light;
+ bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env);
+ energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env);
+ normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env);
+ probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env);
+ reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
}
-void GI::SDFGI::erase() {
- for (uint32_t i = 0; i < cascades.size(); i++) {
- const SDFGI::Cascade &c = cascades[i];
+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 (const SDFGI::Cascade &c : cascades) {
RD::get_singleton()->free(c.light_data);
RD::get_singleton()->free(c.light_aniso_0_tex);
RD::get_singleton()->free(c.light_aniso_1_tex);
@@ -1132,6 +1160,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);
@@ -1155,17 +1184,16 @@ void GI::SDFGI::erase() {
}
}
-void GI::SDFGI::update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position) {
- bounce_feedback = p_env->sdfgi_bounce_feedback;
- energy = p_env->sdfgi_energy;
- normal_bias = p_env->sdfgi_normal_bias;
- probe_bias = p_env->sdfgi_probe_bias;
- reads_sky = p_env->sdfgi_read_sky_light;
+void GI::SDFGI::update(RID p_env, const Vector3 &p_world_position) {
+ bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env);
+ energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env);
+ normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env);
+ probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env);
+ reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
int32_t drag_margin = (cascade_size / SDFGI::PROBE_DIVISOR) / 2;
- for (uint32_t i = 0; i < cascades.size(); i++) {
- SDFGI::Cascade &cascade = cascades[i];
+ for (SDFGI::Cascade &cascade : cascades) {
cascade.dirty_regions = Vector3i();
Vector3 probe_half_size = Vector3(1, 1, 1) * cascade.cell_size * float(cascade_size / SDFGI::PROBE_DIVISOR) * 0.5;
@@ -1252,7 +1280,7 @@ void GI::SDFGI::update_light() {
}
cascades[i].all_dynamic_lights_dirty = false;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_dynamic_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0);
}
@@ -1260,7 +1288,7 @@ void GI::SDFGI::update_light() {
RD::get_singleton()->draw_command_end_label();
}
-void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) {
+void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {
RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes");
SDFGIShader::IntegratePushConstant push_constant;
@@ -1276,29 +1304,29 @@ void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSk
push_constant.ray_bias = probe_bias;
push_constant.image_size[0] = probe_axis_count * probe_axis_count;
push_constant.image_size[1] = probe_axis_count;
- push_constant.store_ambient_texture = p_env->volumetric_fog_enabled;
+ push_constant.store_ambient_texture = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_enabled(p_env);
RID sky_uniform_set = gi->sdfgi_shader.integrate_default_sky_uniform_set;
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_DISABLED;
push_constant.y_mult = y_mult;
- if (reads_sky && p_env) {
- push_constant.sky_energy = p_env->bg_energy;
+ if (reads_sky && p_env.is_valid()) {
+ push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy_multiplier(p_env);
- if (p_env->background == RS::ENV_BG_CLEAR_COLOR) {
+ if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = storage->get_default_clear_color().srgb_to_linear();
+ Color c = RSG::texture_storage->get_default_clear_color().srgb_to_linear();
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
- } else if (p_env->background == RS::ENV_BG_COLOR) {
+ } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = p_env->bg_color;
+ Color c = RendererSceneRenderRD::get_singleton()->environment_get_bg_color(p_env);
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
- } else if (p_env->background == RS::ENV_BG_SKY) {
+ } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_SKY) {
if (p_sky && p_sky->radiance.is_valid()) {
if (integrate_sky_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(integrate_sky_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -1474,7 +1502,7 @@ void GI::SDFGI::update_cascades() {
RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE);
}
-void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *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 GI::SDFGI::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) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
@@ -1490,7 +1518,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
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);
@@ -1503,7 +1531,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
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);
@@ -1516,7 +1544,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
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);
@@ -1529,7 +1557,7 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
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);
@@ -1583,34 +1611,24 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
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..
- CameraMatrix inv_projection = p_projections[v].inverse();
+ 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];
}
}
@@ -1620,11 +1638,11 @@ void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projecti
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 CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
+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) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
// setup scene data
@@ -1636,7 +1654,7 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con
}
for (uint32_t v = 0; v < p_view_count; v++) {
- RendererStorageRD::store_camera(p_camera_with_transforms[v], scene_data.projection[v]);
+ RendererRD::MaterialStorage::store_camera(p_camera_with_transforms[v], scene_data.projection[v]);
}
RD::get_singleton()->buffer_update(debug_probes_scene_data_ubo, 0, sizeof(SDFGIShader::DebugProbesSceneData), &scene_data, RD::BARRIER_MASK_RASTER);
@@ -1774,7 +1792,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;
@@ -1841,6 +1860,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);
@@ -1852,32 +1876,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));
- if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+ 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(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++;
}
@@ -1886,47 +1921,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));
- uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
+ 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(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++;
}
@@ -1939,10 +1996,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<RendererSceneRender::GeometryInstance *> &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;
@@ -1961,7 +2017,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");
@@ -1990,6 +2046,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;
@@ -2272,7 +2329,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");
}
@@ -2298,9 +2355,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");
@@ -2327,21 +2385,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));
- uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
+ 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(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();
@@ -2349,22 +2411,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++;
}
@@ -2406,7 +2486,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
dl_push_constant.cascade = p_cascade_indices[i];
if (dl_push_constant.light_count > 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_static_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0);
}
@@ -2420,7 +2500,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<RendererSceneRender::GeometryInstance *> &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);
@@ -2429,18 +2510,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);
@@ -2459,6 +2529,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(texture, "VoxelGI Instance Texture");
RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1);
@@ -2588,6 +2659,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.texture, "VoxelGI Instance DMap Texture");
if (dynamic_maps.size() == 0) {
// Render depth for first one.
@@ -2595,6 +2667,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.fb_depth, "VoxelGI Instance DMap FB Depth");
}
//just use depth as-is
@@ -2602,13 +2675,17 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.depth, "VoxelGI Instance DMap Depth");
if (dynamic_maps.size() == 0) {
dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.albedo, "VoxelGI Instance DMap Albedo");
dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.normal, "VoxelGI Instance DMap Normal");
dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.orm, "VoxelGI Instance DMap ORM");
Vector<RID> fb;
fb.push_back(dmap.albedo);
@@ -2766,7 +2843,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
@@ -2783,13 +2860,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) {
@@ -2799,16 +2877,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();
@@ -2936,10 +3030,10 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
//this could probably be better parallelized in compute..
for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
- RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i];
+ RenderGeometryInstance *instance = p_dynamic_objects[i];
//transform aabb to voxel_gi
- AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance));
+ AABB aabb = (to_probe_xform * instance->get_transform()).xform(instance->get_aabb());
//this needs to wrap to grid resolution to avoid jitter
//also extend margin a bit just in case
@@ -3000,15 +3094,20 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0);
bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0);
- CameraMatrix cm;
+ 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);
+ }
+ RendererSceneRenderRD::get_singleton()->cull_argument[0] = instance;
+
+ float exposure_normalization = 1.0;
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ exposure_normalization = gi->voxel_gi_get_baked_exposure_normalization(probe);
}
- p_scene_render->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));
+ 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));
@@ -3125,14 +3224,45 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
last_probe_version = gi->voxel_gi_get_version(probe);
}
-void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+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();
if (mipmaps.size() == 0) {
return;
}
- CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse());
+ Projection cam_transform = (p_camera_with_transform * Projection(transform)) * Projection(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse());
int level = 0;
Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
@@ -3150,7 +3280,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];
}
}
@@ -3218,12 +3348,10 @@ GI::~GI() {
singleton = nullptr;
}
-void GI::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
+void GI::init(SkyRD *p_sky) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
-
/* GI */
{
@@ -3339,7 +3467,11 @@ void GI::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_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_WHITE));
+ if (p_sky->sky_use_cubemap_array) {
+ 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::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
+ }
uniforms.push_back(u);
}
{
@@ -3358,38 +3490,45 @@ void GI::init(RendererStorageRD *p_storage, RendererSceneSkyRD *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
gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI
gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_VOXEL_GI
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n"); // MODE_HALF_RES_SDFGI
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_HALF_RES_COMBINED
-
- gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_VOXEL_GI_MULTIVIEW
- gi_modes.push_back("\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_SDFGI_MULTIVIEW
- gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_COMBINED_MULTIVIEW
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_VOXEL_GI_MULTIVIEW
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_SDFGI_MULTIVIEW
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n#define USE_MULTIVIEW\n"); // MODE_HALF_RES_COMBINED_MULTIVIEW
shader.initialize(gi_modes, defines);
+ shader_version = shader.version_create();
+
+ Vector<RD::PipelineSpecializationConstant> specialization_constants;
+
+ {
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 0; // SHADER_SPECIALIZATION_HALF_RES
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
- if (!RendererCompositorRD::singleton->is_xr_enabled()) {
- shader.set_variant_enabled(MODE_VOXEL_GI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_SDFGI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_COMBINED_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_HALF_RES_VOXEL_GI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_HALF_RES_SDFGI_MULTIVIEW, false);
- shader.set_variant_enabled(MODE_HALF_RES_COMBINED_MULTIVIEW, false);
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 1; // SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 2; // SHADER_SPECIALIZATION_USE_VRS
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
}
- shader_version = shader.version_create();
- for (int i = 0; i < MODE_MAX; i++) {
- if (shader.is_variant_enabled(i)) {
- pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i));
- } else {
- pipelines[i] = RID();
+ for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SHADER_SPECIALIZATION_HALF_RES) ? true : false;
+ specialization_constants.ptrw()[1].bool_value = (v & SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX) ? true : false;
+ specialization_constants.ptrw()[2].bool_value = (v & SHADER_SPECIALIZATION_USE_VRS) ? true : false;
+ for (int i = 0; i < MODE_MAX; i++) {
+ pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i), specialization_constants);
}
}
@@ -3457,25 +3596,27 @@ void GI::free() {
}
}
-GI::SDFGI *GI::create_sdfgi(RendererSceneEnvironmentRD *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;
@@ -3486,7 +3627,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;
@@ -3524,37 +3665,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();
}
}
@@ -3567,7 +3715,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]);
@@ -3580,36 +3735,13 @@ void GI::RenderBuffersGI::free() {
scene_data_ubo = RID();
}
- if (ambient_buffer.is_valid()) {
- if (view_count == 1) {
- // Only one view? then these are copies of our main buffers.
- ambient_view[0] = RID();
- reflection_view[0] = RID();
- } else {
- // Multiple views? free our slices.
- for (uint32_t v = 0; v < view_count; v++) {
- RD::get_singleton()->free(ambient_view[v]);
- RD::get_singleton()->free(reflection_view[v]);
- ambient_view[v] = RID();
- reflection_view[v] = RID();
- }
- }
-
- // Now we can free our buffers.
- RD::get_singleton()->free(ambient_buffer);
- RD::get_singleton()->free(reflection_buffer);
- ambient_buffer = RID();
- reflection_buffer = 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, RID *p_normal_roughness_views, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const CameraMatrix *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();
@@ -3617,71 +3749,42 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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()) {
- if (rb->rbgi.view_count > 1) {
- for (uint32_t v = 0; v < rb->rbgi.view_count; v++) {
- RD::get_singleton()->free(rb->rbgi.ambient_view[v]);
- RD::get_singleton()->free(rb->rbgi.reflection_view[v]);
- }
- }
- 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());
+
+ Size2i internal_size = p_render_buffers->get_internal_size();
- print_line("Allocating GI buffers"); // TESTING REMOVE BEFORE MERGING
+ 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());
- rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->rbgi.using_half_size_gi = half_resolution;
-
- if (p_view_count == 1) {
- // Just one view? Copy our buffers
- rb->rbgi.ambient_view[0] = rb->rbgi.ambient_buffer;
- rb->rbgi.reflection_view[0] = rb->rbgi.reflection_buffer;
- } else {
- // More then one view? Create slices for each view
- for (uint32_t v = 0; v < p_view_count; v++) {
- rb->rbgi.ambient_view[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
- rb->rbgi.reflection_view[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++) {
- RendererStorageRD::store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
+ RendererRD::MaterialStorage::store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
@@ -3689,53 +3792,75 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
}
// Note that we will be ignoring the origin of this transform.
- RendererStorageRD::store_transform(p_cam_transform, scene_data.cam_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.
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
- for (uint32_t v = 0; v < p_view_count; v++) {
- // Render each eye seperately.
- // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
+ // Render each eye separately.
+ // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
- // setup our push constant
+ // setup our push constant
- PushConstant push_constant;
+ PushConstant push_constant;
- push_constant.view_index = v;
- push_constant.orthogonal = p_projections[v].is_orthogonal();
- push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
- push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
+ push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
+ push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
+
+ // these should be the same for all views
+ push_constant.orthogonal = p_projections[0].is_orthogonal();
+ push_constant.z_near = p_projections[0].get_z_near();
+ 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 / (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 = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI);
+ bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
- push_constant.z_near = p_projections[v].get_z_near();
- push_constant.z_far = p_projections[v].get_z_far();
+ Ref<SDFGI> sdfgi;
+ if (use_sdfgi) {
+ sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI);
+ }
+
+ uint32_t pipeline_specialization = 0;
+ 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;
+ }
+ bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE);
+ if (has_vrs_texture) {
+ pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;
+ }
- push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[v].matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[v].matrix[1][1]);
- push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0];
- push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1];
+ Mode mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
- bool use_sdfgi = rb->sdfgi != nullptr;
- bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ 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);
@@ -3745,10 +3870,10 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
@@ -3758,10 +3883,10 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
@@ -3771,10 +3896,10 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
@@ -3783,10 +3908,10 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
}
@@ -3809,7 +3934,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 9;
- u.append_id(rb->rbgi.ambient_view[v]);
+ u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0));
uniforms.push_back(u);
}
@@ -3817,7 +3942,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
u.binding = 10;
- u.append_id(rb->rbgi.reflection_view[v]);
+ u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0));
uniforms.push_back(u);
}
@@ -3825,10 +3950,10 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
}
@@ -3836,21 +3961,21 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 13;
- u.append_id(p_normal_roughness_views[v]);
+ u.append_id(p_normal_roughness_slices[v]);
uniforms.push_back(u);
}
{
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);
}
@@ -3865,7 +3990,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
}
{
@@ -3873,7 +3998,7 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
}
@@ -3881,37 +4006,29 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
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);
}
-
- rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
- }
-
- Mode mode;
-
- if (p_view_count > 1) {
- if (rb->rbgi.using_half_size_gi) {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_HALF_RES_SDFGI_MULTIVIEW : MODE_HALF_RES_VOXEL_GI_MULTIVIEW);
- } else {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED_MULTIVIEW : (use_sdfgi ? MODE_SDFGI_MULTIVIEW : MODE_VOXEL_GI_MULTIVIEW);
- }
- } else {
- if (rb->rbgi.using_half_size_gi) {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI);
- } else {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
+ if (RendererSceneRenderRD::get_singleton()->is_vrs_supported()) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 19;
+ 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);
}
+
+ 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[mode]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 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, 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);
}
}
@@ -3923,34 +4040,39 @@ void GI::process_gi(RID p_render_buffers, RID *p_normal_roughness_views, RID p_v
RID GI::voxel_gi_instance_create(RID p_base) {
VoxelGIInstance voxel_gi;
voxel_gi.gi = this;
- voxel_gi.storage = storage;
voxel_gi.probe = p_base;
RID rid = voxel_gi_instance_owner.make_rid(voxel_gi);
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<RendererSceneRender::GeometryInstance *> &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 CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+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) {
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);