summaryrefslogtreecommitdiff
path: root/servers/rendering/renderer_rd
diff options
context:
space:
mode:
Diffstat (limited to 'servers/rendering/renderer_rd')
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.cpp94
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.h9
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp8
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h8
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.cpp4
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h4
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp101
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h18
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp51
-rw-r--r--servers/rendering/renderer_rd/environment/sky.h18
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp82
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h11
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp86
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h12
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp193
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h53
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl18
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/tonemap.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/gi.glsl13
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl1
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl27
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl9
-rw-r--r--servers/rendering/renderer_rd/shaders/light_data_inc.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl45
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl10
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl3
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl49
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl6
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp22
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h11
39 files changed, 664 insertions, 352 deletions
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
index cc7441776d..27850695b0 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
@@ -33,6 +33,8 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/storage/camera_attributes_storage.h"
using namespace RendererRD;
@@ -84,7 +86,7 @@ BokehDOF::~BokehDOF() {
}
}
-void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -92,22 +94,39 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
+ float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
+ float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
+ bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
+ float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
+ float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
+ float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
+
+ bool use_jitter = RSG::camera_attributes->camera_attributes_get_dof_blur_use_jitter();
+ RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
+ RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
+
// setup our push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
- bokeh.push_constant.blur_far_active = p_dof_far;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
-
- bokeh.push_constant.blur_near_active = p_dof_near;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
- bokeh.push_constant.use_jitter = p_use_jitter;
+ bokeh.push_constant.blur_far_active = dof_far;
+ bokeh.push_constant.blur_far_begin = dof_far_begin;
+ bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size; // Only used with non-physically-based.
+ bokeh.push_constant.use_physical_far = dof_far_size < 0.0;
+ bokeh.push_constant.blur_size_far = bokeh_size; // Only used with physically-based.
+
+ bokeh.push_constant.blur_near_active = dof_near;
+ bokeh.push_constant.blur_near_begin = dof_near_begin;
+ bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size; // Only used with non-physically-based.
+ bokeh.push_constant.use_physical_near = dof_near_size < 0.0;
+ bokeh.push_constant.blur_size_near = bokeh_size; // Only used with physically-based.
+
+ bokeh.push_constant.use_jitter = use_jitter;
bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
bokeh.push_constant.z_near = p_cam_znear;
bokeh.push_constant.z_far = p_cam_zfar;
bokeh.push_constant.orthogonal = p_cam_orthogonal;
- bokeh.push_constant.blur_size = p_bokeh_size;
+ bokeh.push_constant.blur_size = (dof_near_size < 0.0 && dof_far_size < 0.0) ? 32 : bokeh_size; // Cap with physically-based to keep performance reasonable.
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
@@ -150,9 +169,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
//second pass
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -160,9 +179,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const int quality_samples[4] = { 6, 12, 12, 24 };
- bokeh.push_constant.steps = quality_samples[p_quality];
+ bokeh.push_constant.steps = quality_samples[blur_quality];
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
@@ -187,7 +206,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
//third pass
bokeh.push_constant.second_pass = true;
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
} else {
@@ -200,7 +219,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//forth pass, upscale for low quality
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
@@ -232,7 +251,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
bokeh.push_constant.steps = 0;
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.blur_scale = quality_scale[blur_quality];
//circle always runs in half size, otherwise too expensive
@@ -273,7 +292,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_end();
}
-void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -281,6 +300,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
+ float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
+ float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
+ bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
+ float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
+ float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
+ float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
+
+ RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
+ RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
+
// setup our base push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
@@ -292,7 +322,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
- bokeh.push_constant.blur_size = p_dof_blur_amount;
+ bokeh.push_constant.blur_size = bokeh_size;
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -307,17 +337,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] }));
RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] }));
- if (p_dof_far || p_dof_near) {
- if (p_dof_far) {
+ if (dof_far || dof_near) {
+ if (dof_far) {
bokeh.push_constant.blur_far_active = true;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
+ bokeh.push_constant.blur_far_begin = dof_far_begin;
+ bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size;
}
- if (p_dof_near) {
+ if (dof_near) {
bokeh.push_constant.blur_near_active = true;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
+ bokeh.push_constant.blur_near_begin = dof_near_begin;
+ bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size;
}
{
@@ -337,14 +367,14 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::get_singleton()->draw_list_end();
}
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
// double pass approach
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
@@ -354,7 +384,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
static const int quality_samples[4] = { 6, 12, 12, 24 };
bokeh.push_constant.blur_scale = 0.5;
- bokeh.push_constant.steps = quality_samples[p_quality];
+ bokeh.push_constant.steps = quality_samples[blur_quality];
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
@@ -373,7 +403,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
// Pass 2
if (!bokeh.push_constant.half_size) {
// do not output weight, we're writing back into our base buffer
- mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
+ mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -432,7 +462,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
}
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.blur_scale = quality_scale[blur_quality];
bokeh.push_constant.steps = 0.0;
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h
index 30b33be168..33dbdfcdc1 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.h
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h
@@ -66,6 +66,11 @@ private:
uint32_t use_jitter;
float jitter_seed;
+ uint32_t use_physical_near;
+ uint32_t use_physical_far;
+
+ float blur_size_near;
+ float blur_size_far;
uint32_t pad[2];
};
@@ -111,8 +116,8 @@ public:
BokehDOF(bool p_prefer_raster_effects);
~BokehDOF();
- void bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
- void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
};
} // namespace RendererRD
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index 5507483cee..70f5fc4a6a 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -654,7 +654,7 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -678,7 +678,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
copy.push_constant.glow_white = 0; //actually unused
copy.push_constant.glow_luminance_cap = p_luminance_cap;
- copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+ copy.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -705,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -729,7 +729,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
blur_raster.push_constant.glow_white = 0; //actually unused
blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
- blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+ blur_raster.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier;
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index d25555eee5..f82726d654 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -86,7 +86,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
float luminance_multiplier;
float res1;
@@ -148,7 +148,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
// DOF.
float camera_z_far;
float camera_z_near;
@@ -321,8 +321,8 @@ public:
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
index 38a4a37b8a..3a47b1420b 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
@@ -117,7 +117,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
@@ -203,7 +203,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
index 05db4a0cbe..e91118e241 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.h
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -77,7 +77,7 @@ private:
float exposure; // 4 - 84
float white; // 4 - 88
- float auto_exposure_grey; // 4 - 92
+ float auto_exposure_scale; // 4 - 92
float luminance_multiplier; // 4 - 96
float pixel_size[2]; // 8 - 104
@@ -124,7 +124,7 @@ public:
float white = 1.0;
bool use_auto_exposure = false;
- float auto_exposure_grey = 0.5;
+ float auto_exposure_scale = 0.5;
RID exposure_texture;
float luminance_multiplier = 1.0;
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 66e984174c..bc4f8d5855 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -287,6 +287,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);
@@ -1292,7 +1305,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;
@@ -1840,6 +1853,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);
@@ -1876,6 +1894,14 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
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);
+ if (p_scene_render->is_using_physical_light_units()) {
+ lights[idx].energy *= RSG::light_storage->light_get_param(li->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(li->light);
idx++;
@@ -1920,7 +1946,25 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_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);
+ if (p_scene_render->is_using_physical_light_units()) {
+ lights[idx].energy *= RSG::light_storage->light_get_param(li->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(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);
@@ -1938,7 +1982,7 @@ 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(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, 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...
@@ -1960,7 +2004,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);
+ p_scene_render->_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");
@@ -1989,6 +2033,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;
@@ -2297,7 +2342,7 @@ 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) {
+void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, 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...
@@ -2358,7 +2403,25 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co
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);
+ if (p_scene_render->is_using_physical_light_units()) {
+ lights[idx].energy *= RSG::light_storage->light_get_param(li->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(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);
@@ -2794,6 +2857,22 @@ 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 (p_scene_render->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;
@@ -3003,7 +3082,12 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID
}
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));
+ float exposure_normalization = 1.0;
+ if (p_scene_render->is_using_physical_light_units()) {
+ exposure_normalization = gi->voxel_gi_get_baked_exposure_normalization(probe);
+ }
+
+ p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size), exposure_normalization);
VoxelGIDynamicPushConstant push_constant;
memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant));
@@ -3496,7 +3580,7 @@ GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t
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, 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) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
r_voxel_gi_instances_used = 0;
@@ -3555,6 +3639,11 @@ 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++;
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index 8860445c3b..9ef1914333 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -76,6 +76,7 @@ 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.5;
@@ -398,6 +399,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;
@@ -512,6 +516,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
@@ -551,6 +556,8 @@ public:
RID integrate_uniform_set;
RID lights_buffer;
+ float baked_exposure_normalization = 1.0;
+
bool all_dynamic_lights_dirty = true;
};
@@ -630,8 +637,8 @@ public:
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 render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
+ void render_static_lights(RenderDataRD *p_render_data, 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);
};
RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
@@ -705,6 +712,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];
@@ -720,6 +729,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 {
@@ -777,7 +789,7 @@ public:
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 setup_voxel_gi_instances(RenderDataRD *p_render_data, 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);
RID voxel_gi_instance_create(RID p_base);
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 1d6b158d65..d1d18cdd83 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -292,7 +292,7 @@ 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, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
@@ -307,7 +307,6 @@ void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineC
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);
@@ -762,7 +761,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;
@@ -868,7 +867,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";
@@ -1110,7 +1109,7 @@ 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(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_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());
@@ -1220,6 +1219,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;
@@ -1351,8 +1358,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;
@@ -1415,7 +1420,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
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, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1434,7 +1439,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
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, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1449,7 +1454,7 @@ void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
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, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1475,7 +1480,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 {
@@ -1491,7 +1496,7 @@ 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::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, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
ERR_FAIL_COND(p_env.is_null());
@@ -1536,7 +1541,6 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
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
@@ -1567,7 +1571,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
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);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@@ -1580,7 +1584,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
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);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@@ -1594,7 +1598,7 @@ void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth
}
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);
+ _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@@ -1634,7 +1638,6 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio
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
@@ -1665,7 +1668,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio
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);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@@ -1678,7 +1681,7 @@ void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projectio
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);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
}
@@ -1728,7 +1731,6 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie
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
@@ -1759,7 +1761,7 @@ void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_vie
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, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
}
void SkyRD::invalidate_sky(Sky *p_sky) {
@@ -1881,6 +1883,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 080165c112..bac8f44ef7 100644
--- a/servers/rendering/renderer_rd/environment/sky.h
+++ b/servers/rendering/renderer_rd/environment/sky.h
@@ -100,10 +100,9 @@ private:
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 time; // 4 - 96
+ float pad[3]; // 12 - 108
+ float luminance_multiplier; // 4 - 112
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
@@ -143,7 +142,7 @@ private:
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, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
@@ -264,6 +263,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;
@@ -296,9 +296,9 @@ public:
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 setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, 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 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, float p_luminance_multiplier = 1.0); // 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);
@@ -306,6 +306,8 @@ public:
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 +317,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
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 8754e90647..8421598275 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -906,8 +906,9 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment);
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
- scene_state.ubo.ambient_light_color_energy[3] = bg_energy;
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
+
+ scene_state.ubo.ambient_light_color_energy[3] = bg_energy_multiplier;
scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment);
@@ -916,9 +917,9 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
color = color.srgb_to_linear();
- scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
- scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
- scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy;
+ scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier;
+ scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier;
+ scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier;
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.use_ambient_cubemap = false;
} else {
@@ -987,6 +988,25 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.ss_effects_flags = 0;
}
+ if (p_render_data->camera_attributes.is_valid()) {
+ scene_state.ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ scene_state.ubo.IBL_exposure_normalization = 1.0;
+ if (is_environment(p_render_data->environment)) {
+ RID sky_rid = environment_get_sky(p_render_data->environment);
+ if (sky_rid.is_valid()) {
+ float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes) * environment_get_bg_intensity(p_render_data->environment) / _render_buffers_get_luminance_multiplier();
+ scene_state.ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, sky.sky_get_baked_exposure(sky_rid));
+ }
+ }
+ } else if (scene_state.ubo.emissive_exposure_normalization > 0.0) {
+ // This branch is triggered when using render_material().
+ // Emissive is set outside the function, so don't set it.
+ // IBL isn't used don't set it.
+ } else {
+ scene_state.ubo.emissive_exposure_normalization = 1.0;
+ scene_state.ubo.IBL_exposure_normalization = 1.0;
+ }
+
scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();
@@ -1383,7 +1403,7 @@ void RenderForwardClustered::_setup_voxelgis(const PagedArray<RID> &p_voxelgis)
}
}
-void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
+void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
@@ -1395,6 +1415,13 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ scene_state.lightmaps[i].exposure_normalization = 1.0;
+ if (p_render_data->camera_attributes.is_valid()) {
+ float baked_exposure = RendererRD::LightStorage::get_singleton()->lightmap_get_baked_exposure_normalization(lightmap);
+ float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
+ }
+
scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
@@ -1513,9 +1540,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
scene_state.ubo.viewport_size[0] = screen_size.x;
scene_state.ubo.viewport_size[1] = screen_size.y;
+ scene_state.ubo.emissive_exposure_normalization = -1.0;
+
RD::get_singleton()->draw_command_begin_label("Render Setup");
- _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
+ _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->cam_transform);
_setup_voxelgis(*p_render_data->voxel_gi_instances);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
@@ -1539,6 +1568,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID radiance_texture;
bool draw_sky = false;
bool draw_sky_fog_only = false;
+ // We invert luminance_multiplier for sky so that we can combine it with exposure value.
+ float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
Color clear_color;
bool keep_color = false;
@@ -1547,13 +1578,19 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
+ bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
clear_color = p_default_bg_color;
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
@@ -1561,9 +1598,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(p_render_data->environment);
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
@@ -1594,11 +1631,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
projection = correction * p_render_data->cam_projection;
}
- sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
+ sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->cam_transform, screen_size, this);
+
+ sky_energy_multiplier *= bg_energy_multiplier;
RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time);
+ sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -1753,9 +1792,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
Projection correction;
correction.set_depth_correction(true);
Projection projection = correction * p_render_data->cam_projection;
- sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier);
} else {
- sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label();
}
@@ -2000,7 +2039,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@@ -2018,6 +2057,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
scene_state.ubo.opaque_prepass_threshold = 0.0f;
+ scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -2064,6 +2104,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
scene_state.ubo.opaque_prepass_threshold = 0.0;
+ scene_state.ubo.emissive_exposure_normalization = -1.0;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -2119,7 +2160,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
RENDER_TIMESTAMP("Render SDFGI");
RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel");
@@ -2187,6 +2228,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds);
+ scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 7e71406af8..3d74f6769e 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -218,6 +218,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
struct LightmapData {
float normal_xform[12];
+ float pad[3];
+ float exposure_normalization;
};
struct LightmapCaptureData {
@@ -324,7 +326,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t pancake_shadows;
float taa_jitter[2];
- uint32_t pad[2];
+ float emissive_exposure_normalization; // Needed to normalize emissive when using physical units.
+ float IBL_exposure_normalization;
};
struct PushConstant {
@@ -397,7 +400,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
void _setup_voxelgis(const PagedArray<RID> &p_voxelgis);
- void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
+ void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
struct RenderElementInfo {
enum { MAX_REPEATS = (1 << 20) - 1 };
@@ -618,9 +621,9 @@ protected:
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
public:
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index ffd47cc163..67d001dcb7 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -469,7 +469,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
return render_pass_uniform_sets[p_index];
}
-void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
+void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
// This probably needs to change...
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
@@ -482,6 +482,13 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ scene_state.lightmaps[i].exposure_normalization = 1.0;
+ if (p_render_data->camera_attributes.is_valid()) {
+ float baked_exposure = RendererRD::LightStorage::get_singleton()->lightmap_get_baked_exposure_normalization(lightmap);
+ float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
+ }
+
scene_state.lightmap_ids[i] = p_lightmaps[i];
scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
@@ -539,7 +546,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
// can't do blit subpass
using_subpass_post_process = false;
- } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || environment_get_auto_exposure(p_render_data->environment) || camera_effects_uses_dof(p_render_data->camera_effects))) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
// can't do blit subpass
using_subpass_post_process = false;
}
@@ -580,10 +587,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
scene_state.ubo.viewport_size[0] = screen_size.x;
scene_state.ubo.viewport_size[1] = screen_size.y;
+ scene_state.ubo.emissive_exposure_normalization = -1.0;
RD::get_singleton()->draw_command_begin_label("Render Setup");
- _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
+ _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->cam_transform);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
@@ -594,6 +602,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RID radiance_texture;
bool draw_sky = false;
bool draw_sky_fog_only = false;
+ // We invert luminance_multiplier for sky so that we can combine it with exposure value.
+ float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
Color clear_color = p_default_bg_color;
bool keep_color = false;
@@ -602,13 +612,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
+ bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
clear_color = p_default_bg_color;
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
@@ -618,9 +634,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(p_render_data->environment);
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
/*
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
@@ -653,11 +669,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
projection = correction * p_render_data->cam_projection;
}
- sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
+ sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->cam_transform, screen_size, this);
+
+ sky_energy_multiplier *= bg_energy_multiplier;
RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -681,9 +699,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Projection correction;
correction.set_depth_correction(true);
Projection projection = correction * p_render_data->cam_projection;
- sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->cam_transform, time);
+ sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier);
} else {
- sky.update_res_buffers(p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.update_res_buffers(p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
@@ -780,9 +798,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
Projection correction;
correction.set_depth_correction(true);
Projection projection = correction * p_render_data->cam_projection;
- sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier);
} else {
- sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
@@ -999,7 +1017,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
/* */
-void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
@@ -1009,6 +1027,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = false;
scene_state.ubo.opaque_prepass_threshold = 0.0f;
+ scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization;
RenderDataRD render_data;
render_data.cam_projection = p_cam_projection;
@@ -1054,6 +1073,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
scene_state.ubo.dual_paraboloid_side = 0;
scene_state.ubo.material_uv2_mode = true;
+ scene_state.ubo.emissive_exposure_normalization = -1.0;
RenderDataRD render_data;
render_data.instances = &p_instances;
@@ -1112,7 +1132,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
// we don't do GI in low end..
}
@@ -1650,8 +1670,9 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment);
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
- scene_state.ubo.ambient_light_color_energy[3] = bg_energy;
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
+
+ scene_state.ubo.ambient_light_color_energy[3] = bg_energy_multiplier;
scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment);
@@ -1660,9 +1681,9 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
color = color.srgb_to_linear();
- scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
- scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
- scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy;
+ scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier;
+ scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier;
+ scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier;
scene_state.ubo.use_ambient_light = true;
scene_state.ubo.use_ambient_cubemap = false;
} else {
@@ -1726,6 +1747,25 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
scene_state.ubo.ssao_enabled = false;
}
+ if (p_render_data->camera_attributes.is_valid()) {
+ scene_state.ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ scene_state.ubo.IBL_exposure_normalization = 1.0;
+ if (is_environment(p_render_data->environment)) {
+ RID sky_rid = environment_get_sky(p_render_data->environment);
+ if (sky_rid.is_valid()) {
+ float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes) * environment_get_bg_intensity(p_render_data->environment) / _render_buffers_get_luminance_multiplier();
+ scene_state.ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, sky.sky_get_baked_exposure(sky_rid));
+ }
+ }
+ } else if (scene_state.ubo.emissive_exposure_normalization > 0.0) {
+ // This branch is triggered when using render_material().
+ // Emissive is set outside the function, so don't set it.
+ // IBL isn't used don't set it.
+ } else {
+ scene_state.ubo.emissive_exposure_normalization = 1.0;
+ scene_state.ubo.IBL_exposure_normalization = 1.0;
+ }
+
scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index 4a7112eb81..cc3e245f2f 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -216,9 +216,9 @@ protected:
virtual void _render_shadow_process() override;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
@@ -235,7 +235,7 @@ protected:
static RenderForwardMobile *singleton;
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
- void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
+ void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
RID render_base_uniform_set;
LocalVector<RID> render_pass_uniform_sets;
@@ -244,6 +244,8 @@ protected:
struct LightmapData {
float normal_xform[12];
+ float pad[3];
+ float exposure_normalization;
};
struct LightmapCaptureData {
@@ -315,8 +317,8 @@ protected:
float reflection_multiplier;
uint32_t pancake_shadows;
- uint32_t pad1;
- uint32_t pad2;
+ float emissive_exposure_normalization; // Needed to normalize emissive when using physical units.
+ float IBL_exposure_normalization; // Adjusts for baked exposure.
uint32_t pad3;
};
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index fa83428367..a95dbbe779 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -37,6 +37,7 @@
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/storage/camera_attributes_storage.h"
void get_vogel_disk(float *r_kernel, int p_sample_count) {
const float golden_angle = 2.4;
@@ -246,7 +247,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
}
if (use_cube_map) {
- Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy(p_env), p_bake_irradiance, p_size);
+ Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy_multiplier(p_env), p_bake_irradiance, p_size);
if (use_ambient_light) {
for (int x = 0; x < p_size.width; x++) {
for (int y = 0; y < p_size.height; y++) {
@@ -256,12 +257,12 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
}
return panorama;
} else {
- const float bg_energy = environment_get_bg_energy(p_env);
+ const float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_env);
Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : environment_get_bg_color(p_env));
panorama_color = panorama_color.srgb_to_linear();
- panorama_color.r *= bg_energy;
- panorama_color.g *= bg_energy;
- panorama_color.b *= bg_energy;
+ panorama_color.r *= bg_energy_multiplier;
+ panorama_color.g *= bg_energy_multiplier;
+ panorama_color.b *= bg_energy_multiplier;
if (use_ambient_light) {
panorama_color = ambient_color.lerp(panorama_color, ambient_color_sky_mix);
@@ -1083,45 +1084,6 @@ int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance
//////////////////////////////////////////////////
-RID RendererSceneRenderRD::camera_effects_allocate() {
- return camera_effects_owner.allocate_rid();
-}
-void RendererSceneRenderRD::camera_effects_initialize(RID p_rid) {
- camera_effects_owner.initialize_rid(p_rid, CameraEffects());
-}
-
-void RendererSceneRenderRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
- dof_blur_quality = p_quality;
- dof_blur_use_jitter = p_use_jitter;
-}
-
-void RendererSceneRenderRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {
- dof_blur_bokeh_shape = p_shape;
-}
-
-void RendererSceneRenderRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) {
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
- ERR_FAIL_COND(!camfx);
-
- camfx->dof_blur_far_enabled = p_far_enable;
- camfx->dof_blur_far_distance = p_far_distance;
- camfx->dof_blur_far_transition = p_far_transition;
-
- camfx->dof_blur_near_enabled = p_near_enable;
- camfx->dof_blur_near_distance = p_near_distance;
- camfx->dof_blur_near_transition = p_near_transition;
-
- camfx->dof_blur_amount = p_amount;
-}
-
-void RendererSceneRenderRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
- ERR_FAIL_COND(!camfx);
-
- camfx->override_exposure_enabled = p_enable;
- camfx->override_exposure = p_exposure;
-}
-
RID RendererSceneRenderRD::light_instance_create(RID p_light) {
RID li = light_instance_owner.make_rid(LightInstance());
@@ -1860,13 +1822,11 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- // Glow and override exposure (if enabled).
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
-
+ // Glow, auto exposure and DoF (if enabled).
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
bool can_use_storage = _render_buffers_can_be_storage();
- if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Depth of Field");
RD::get_singleton()->draw_command_begin_label("DOF");
if (rb->blur[0].texture.is_null()) {
@@ -1881,7 +1841,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture;
buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture;
- float bokeh_size = camfx->dof_blur_amount * 64.0;
if (can_use_storage) {
for (uint32_t i = 0; i < rb->view_count; i++) {
buffers.base_texture = rb->views[i].view_texture;
@@ -1890,7 +1849,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
float z_near = p_render_data->view_projection[i].get_z_near();
float z_far = p_render_data->view_projection[i].get_z_far();
- bokeh_dof->bokeh_dof_compute(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, z_near, z_far, p_render_data->cam_orthogonal);
+ bokeh_dof->bokeh_dof_compute(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->cam_orthogonal);
};
} else {
// Set framebuffers.
@@ -1913,27 +1872,32 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
float z_near = p_render_data->view_projection[i].get_z_near();
float z_far = p_render_data->view_projection[i].get_z_far();
- bokeh_dof->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, z_near, z_far, p_render_data->cam_orthogonal);
+ bokeh_dof->bokeh_dof_raster(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->cam_orthogonal);
}
}
RD::get_singleton()->draw_command_end_label();
}
- if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) {
+ float auto_exposure_scale = 1.0;
+
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Auto exposure");
+
RD::get_singleton()->draw_command_begin_label("Auto exposure");
if (rb->luminance.current.is_null()) {
_allocate_luminance_textures(rb);
}
+ uint64_t auto_exposure_version = RSG::camera_attributes->camera_attributes_get_auto_exposure_version(p_render_data->camera_attributes);
+ bool set_immediate = auto_exposure_version != rb->auto_exposure_version;
+ rb->auto_exposure_version = auto_exposure_version;
- bool set_immediate = environment_get_auto_exposure_version(p_render_data->environment) != rb->auto_exposure_version;
- rb->auto_exposure_version = environment_get_auto_exposure_version(p_render_data->environment);
-
- double step = environment_get_auto_exp_speed(p_render_data->environment) * time_step;
+ double step = RSG::camera_attributes->camera_attributes_get_auto_exposure_adjust_speed(p_render_data->camera_attributes) * time_step;
+ float auto_exposure_min_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_min_sensitivity(p_render_data->camera_attributes);
+ float auto_exposure_max_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_max_sensitivity(p_render_data->camera_attributes);
if (can_use_storage) {
- RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), step, set_immediate);
+ RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
} else {
- RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, environment_get_min_luminance(p_render_data->environment), environment_get_max_luminance(p_render_data->environment), step, set_immediate);
+ RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
}
// Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
@@ -1941,6 +1905,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
}
+ auto_exposure_scale = RSG::camera_attributes->camera_attributes_get_auto_exposure_scale(p_render_data->camera_attributes);
+
RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on.
RD::get_singleton()->draw_command_end_label();
}
@@ -1975,13 +1941,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
if (i == 0) {
RID luminance_texture;
- if (environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) {
+ if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
luminance_texture = rb->luminance.current;
}
if (can_use_storage) {
- copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment));
+ copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
} else {
- copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, environment_get_auto_exp_scale(p_render_data->environment));
+ copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
}
} else {
if (can_use_storage) {
@@ -2002,10 +1968,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RendererRD::ToneMapper::TonemapSettings tonemap;
- if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment) && rb->luminance.current.is_valid()) {
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
tonemap.use_auto_exposure = true;
tonemap.exposure_texture = rb->luminance.current;
- tonemap.auto_exposure_grey = environment_get_auto_exp_scale(p_render_data->environment);
+ tonemap.auto_exposure_scale = auto_exposure_scale;
} else {
tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
@@ -2047,10 +2013,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.exposure = environment_get_exposure(p_render_data->environment);
}
- if (camfx && camfx->override_exposure_enabled) {
- tonemap.exposure = camfx->override_exposure;
- }
-
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
@@ -2093,9 +2055,6 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
ERR_FAIL_COND(!rb);
- // Override exposure (if enabled).
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
-
bool can_use_effects = rb->width >= 8 && rb->height >= 8;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
@@ -2108,18 +2067,15 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
tonemap.white = environment_get_white(p_render_data->environment);
}
- if (camfx && camfx->override_exposure_enabled) {
- tonemap.exposure = camfx->override_exposure;
- }
-
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
// The problem is that we need to use the result so far and process them before we can
// apply this to our results.
if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
}
- if (can_use_effects && p_render_data->environment.is_valid() && environment_get_auto_exposure(p_render_data->environment)) {
- ERR_FAIL_MSG("Glow is not supported when using subpasses.");
+
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
+ ERR_FAIL_MSG("Auto Exposure is not supported when using subpasses.");
}
tonemap.use_glow = false;
@@ -2739,7 +2695,7 @@ RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_g
return rb->data;
}
-void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
+void RendererSceneRenderRD::_setup_reflections(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
cluster.reflection_count = 0;
@@ -2796,6 +2752,12 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
reflection_ubo.exterior = !light_storage->reflection_probe_is_interior(base_probe);
reflection_ubo.box_project = light_storage->reflection_probe_is_box_projection(base_probe);
+ reflection_ubo.exposure_normalization = 1.0;
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ float exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ reflection_ubo.exposure_normalization = exposure / light_storage->reflection_probe_get_baked_exposure(base_probe);
+ }
Color ambient_linear = light_storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear();
float interior_ambient_energy = light_storage->reflection_probe_get_ambient_color_energy(base_probe);
@@ -2819,7 +2781,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
}
}
-void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
+void RendererSceneRenderRD::_setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
@@ -2863,7 +2825,17 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
float sign = light_storage->light_is_negative(base) ? -1 : 1;
- light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
+ light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
+
+ if (is_using_physical_light_units()) {
+ light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
+ } else {
+ light_data.energy *= Math_PI;
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
light_data.color[0] = linear_col.r;
@@ -3076,7 +3048,26 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
}
}
- float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
+ float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * fade;
+
+ if (is_using_physical_light_units()) {
+ energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
+
+ // Convert from Luminous Power to Luminous Intensity
+ if (type == RS::LIGHT_OMNI) {
+ energy *= 1.0 / (Math_PI * 4.0);
+ } else {
+ // 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.
+ energy *= 1.0 / Math_PI;
+ }
+ } else {
+ energy *= Math_PI;
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
light_data.color[0] = linear_col.r * energy;
light_data.color[1] = linear_col.g * energy;
@@ -3645,12 +3636,12 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
} else {
//do not render reflections when rendering a reflection probe
- _setup_reflections(*p_render_data->reflection_probes, p_render_data->cam_transform.affine_inverse(), p_render_data->environment);
+ _setup_reflections(p_render_data, *p_render_data->reflection_probes, p_render_data->cam_transform.affine_inverse(), p_render_data->environment);
}
uint32_t directional_light_count = 0;
uint32_t positional_light_count = 0;
- _setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
+ _setup_lights(p_render_data, *p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
_setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse());
p_render_data->directional_light_count = directional_light_count;
@@ -3673,7 +3664,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
}
}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
// getting this here now so we can direct call a bunch of things more easily
@@ -3719,7 +3710,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.lightmaps = &p_lightmaps;
render_data.fog_volumes = &p_fog_volumes;
render_data.environment = p_environment;
- render_data.camera_effects = p_camera_effects;
+ render_data.camera_attributes = p_camera_attributes;
render_data.shadow_atlas = p_shadow_atlas;
render_data.reflection_atlas = p_reflection_atlas;
render_data.reflection_probe = p_reflection_probe;
@@ -3753,11 +3744,15 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
//sdfgi first
if (rb != nullptr && rb->sdfgi != nullptr) {
+ float exposure_normalization = 1.0;
+ if (p_camera_attributes.is_valid()) {
+ exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes);
+ }
for (int i = 0; i < render_state.render_sdfgi_region_count; i++) {
- rb->sdfgi->render_region(p_render_buffers, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this);
+ rb->sdfgi->render_region(p_render_buffers, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this, exposure_normalization);
}
if (render_state.sdfgi_update_data->update_static) {
- rb->sdfgi->render_static_lights(p_render_buffers, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this);
+ rb->sdfgi->render_static_lights(&render_data, p_render_buffers, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this);
}
}
@@ -3790,6 +3785,9 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
} else {
current_cluster_builder = ra->cluster_builder;
}
+ if (p_camera_attributes.is_valid()) {
+ RendererRD::LightStorage::get_singleton()->reflection_probe_set_baked_exposure(rpi->probe, RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes));
+ }
} else {
ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
current_cluster_builder = nullptr;
@@ -3804,7 +3802,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
rb->sdfgi->update_light();
}
- gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
+ gi.setup_voxel_gi_instances(&render_data, render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
}
render_state.depth_prepass_used = false;
@@ -4041,7 +4039,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas,
}
void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
- _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region);
+ _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region, 1.0);
}
void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
@@ -4083,9 +4081,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {
render_buffers_owner.free(p_rid);
} else if (is_environment(p_rid)) {
environment_free(p_rid);
- } else if (camera_effects_owner.owns(p_rid)) {
- //not much to delete, just free it
- camera_effects_owner.free(p_rid);
+ } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
+ RSG::camera_attributes->camera_attributes_free(p_rid);
} else if (reflection_atlas_owner.owns(p_rid)) {
reflection_atlas_set_size(p_rid, 0, 0);
ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_rid);
@@ -4335,8 +4332,8 @@ RendererSceneRenderRD::RendererSceneRenderRD() {
void RendererSceneRenderRD::init() {
max_cluster_elements = get_max_elements();
- directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
- directional_shadow.use_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits");
+ directional_shadow.size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size");
+ directional_shadow.use_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits");
/* SKY SHADER */
@@ -4395,8 +4392,10 @@ void RendererSceneRenderRD::init() {
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
- camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))));
- camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"));
+ RSG::camera_attributes->camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))));
+ RSG::camera_attributes->camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"));
+ use_physical_light_units = GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units");
+
environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
screen_space_roughness_limiter = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled");
screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount");
@@ -4414,8 +4413,8 @@ void RendererSceneRenderRD::init() {
directional_soft_shadow_kernel = memnew_arr(float, 128);
penumbra_shadow_kernel = memnew_arr(float, 128);
soft_shadow_kernel = memnew_arr(float, 128);
- positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality"))));
- directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality"))));
+ positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality"))));
+ directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality"))));
environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"));
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 3867fd8605..70109b29da 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -76,7 +76,7 @@ struct RenderDataRD {
const PagedArray<RID> *lightmaps = nullptr;
const PagedArray<RID> *fog_volumes = nullptr;
RID environment;
- RID camera_effects;
+ RID camera_attributes;
RID shadow_atlas;
RID reflection_atlas;
RID reflection_probe;
@@ -114,9 +114,9 @@ protected:
};
virtual RenderBufferData *_create_render_buffer_data() = 0;
- void _setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
+ void _setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
- void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
+ void _setup_reflections(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
@@ -125,9 +125,9 @@ protected:
virtual void _render_shadow_process() = 0;
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
- virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) = 0;
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
+ virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
@@ -418,31 +418,11 @@ private:
bool glow_high_quality = false;
RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
- /* CAMERA EFFECTS */
-
- struct CameraEffects {
- bool dof_blur_far_enabled = false;
- float dof_blur_far_distance = 10;
- float dof_blur_far_transition = 5;
-
- bool dof_blur_near_enabled = false;
- float dof_blur_near_distance = 2;
- float dof_blur_near_transition = 1;
-
- float dof_blur_amount = 0.1;
-
- bool override_exposure_enabled = false;
- float override_exposure = 1;
- };
-
- RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM;
- RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON;
- bool dof_blur_use_jitter = false;
RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM;
float sss_scale = 0.05;
float sss_depth_scale = 0.01;
- mutable RID_Owner<CameraEffects, true> camera_effects_owner;
+ bool use_physical_light_units = false;
/* RENDER BUFFERS */
@@ -592,7 +572,7 @@ private:
uint32_t exterior;
uint32_t box_project;
uint32_t ambient_mode;
- uint32_t pad;
+ float exposure_normalization;
float local_matrix[16]; // up to here for spot and omni, rest is for directional
};
@@ -831,21 +811,8 @@ public:
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
- /* CAMERA EFFECTS */
-
- virtual RID camera_effects_allocate() override;
- virtual void camera_effects_initialize(RID p_rid) override;
-
- virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override;
- virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override;
-
- virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
- virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
-
- bool camera_effects_uses_dof(RID p_camera_effects) {
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
-
- return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
+ _FORCE_INLINE_ bool is_using_physical_light_units() {
+ return use_physical_light_units;
}
/* LIGHT INSTANCE API */
@@ -1139,7 +1106,7 @@ public:
virtual void update_uniform_sets(){};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
index 96f5c3e9f2..cb06250cf2 100644
--- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
@@ -129,7 +129,7 @@ void main() {
#ifdef GLOW_USE_AUTO_EXPOSURE
- frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
+ frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_scale;
#endif
frag_color *= blur.glow_exposure;
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
index 730504571a..06ca198f37 100644
--- a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
@@ -16,7 +16,7 @@ layout(push_constant, std430) uniform Blur {
float glow_exposure; // 04 - 36
float glow_white; // 04 - 40
float glow_luminance_cap; // 04 - 44
- float glow_auto_exposure_grey; // 04 - 48
+ float glow_auto_exposure_scale; // 04 - 48
float luminance_multiplier; // 04 - 52
float res1; // 04 - 56
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index 0b43af7738..bdf84bb03a 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
@@ -41,11 +41,25 @@ float get_depth_at_pos(vec2 uv) {
float get_blur_size(float depth) {
if (params.blur_near_active && depth < params.blur_near_begin) {
- return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
+ if (params.use_physical_near) {
+ // Physically-based.
+ float d = abs(params.blur_near_begin - depth);
+ return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative.
+ } else {
+ // Non-physically-based.
+ return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative.
+ }
}
if (params.blur_far_active && depth > params.blur_far_begin) {
- return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ if (params.use_physical_far) {
+ // Physically-based.
+ float d = abs(params.blur_far_begin - depth);
+ return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP;
+ } else {
+ // Non-physically-based.
+ return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ }
}
return 0.0;
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
index b90a527554..4a2b0edc18 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
@@ -20,6 +20,11 @@ layout(push_constant, std430) uniform Params {
bool use_jitter;
float jitter_seed;
+ bool use_physical_near;
+ bool use_physical_far;
+
+ float blur_size_near;
+ float blur_size_far;
uint pad[2];
}
params;
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index a06cacfabe..a2bdc2e90e 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
@@ -63,11 +63,25 @@ float get_depth_at_pos(vec2 uv) {
float get_blur_size(float depth) {
if (params.blur_near_active && depth < params.blur_near_begin) {
- return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
+ if (params.use_physical_near) {
+ // Physically-based.
+ float d = abs(params.blur_near_begin - depth);
+ return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative.
+ } else {
+ // Non-physically-based.
+ return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative.
+ }
}
if (params.blur_far_active && depth > params.blur_far_begin) {
- return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ if (params.use_physical_far) {
+ // Physically-based.
+ float d = abs(params.blur_far_begin - depth);
+ return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP;
+ } else {
+ // Non-physically-based.
+ return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ }
}
return 0.0;
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
index 3a4ef86ef0..bfe329b8ec 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
@@ -31,7 +31,7 @@ layout(push_constant, std430) uniform Params {
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
// DOF.
float camera_z_far;
float camera_z_near;
@@ -185,7 +185,7 @@ void main() {
if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
#ifdef GLOW_USE_AUTO_EXPOSURE
- color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey;
+ color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_scale;
#endif
color *= params.glow_exposure;
diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
index 62a7b0e7d7..e459756c6a 100644
--- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
@@ -75,7 +75,7 @@ layout(push_constant, std430) uniform Params {
float exposure;
float white;
- float auto_exposure_grey;
+ float auto_exposure_scale;
float luminance_multiplier;
vec2 pixel_size;
@@ -440,7 +440,7 @@ void main() {
#ifndef SUBPASS
if (params.use_auto_exposure) {
- exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_grey);
+ exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_scale);
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/environment/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
index 6ea8cb1377..ab927df678 100644
--- a/servers/rendering/renderer_rd/shaders/environment/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
@@ -32,6 +32,8 @@ struct ProbeCascadeData {
float to_probe;
ivec3 probe_world_offset;
float to_cell; // 1/bounds * grid_size
+ vec3 pad;
+ float exposure_normalization;
};
layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image2D ambient_buffer;
@@ -83,6 +85,9 @@ struct VoxelGIData {
float normal_bias; // 4 - 88
bool blend_ambient; // 4 - 92
uint mipmaps; // 4 - 96
+
+ vec3 pad; // 12 - 108
+ float exposure_normalization; // 4 - 112
};
layout(set = 0, binding = 16, std140) uniform VoxelGIs {
@@ -241,7 +246,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
diffuse = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
- diffuse_accum += vec4(diffuse * weight, weight);
+ diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight);
{
vec3 specular = vec3(0.0);
@@ -255,7 +260,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_
specular = mix(specular, textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb, (roughness - 0.2) * 1.25);
}
- specular_accum += specular * weight;
+ specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization;
}
}
@@ -574,7 +579,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
}
}
- light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
if (!voxel_gi_instances.data[index].blend_ambient) {
light.a = 1.0;
}
@@ -583,7 +588,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
//radiance
vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias);
- irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
if (!voxel_gi_instances.data[index].blend_ambient) {
irr_light.a = 1.0;
}
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
index 9640d30e78..177dab16c7 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
@@ -21,6 +21,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 9, std140) uniform Cascades {
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl
index 75b1ad2130..a0ef169f03 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl
@@ -73,6 +73,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 1, std140) uniform Cascades {
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
index b95fad650e..9f7449b8aa 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
@@ -45,6 +45,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 8, std140) uniform Cascades {
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl
index 9c03297f5c..4bdb0dcc72 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl
@@ -20,6 +20,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 7, std140) uniform Cascades {
diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index e825020a4e..7a0b2af3ce 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
@@ -15,10 +15,10 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, std430) uniform Params {
mat3 orientation;
vec4 projections[MAX_VIEWS];
- vec4 position_multiplier;
+ vec3 position;
float time;
+ vec3 pad;
float luminance_multiplier;
- float pad[2];
}
params;
@@ -55,10 +55,10 @@ layout(location = 0) in vec2 uv_interp;
layout(push_constant, std430) uniform Params {
mat3 orientation;
vec4 projections[MAX_VIEWS];
- vec4 position_multiplier;
+ vec3 position;
float time;
+ vec3 pad;
float luminance_multiplier;
- float pad[2];
}
params;
@@ -200,17 +200,17 @@ void main() {
#ifdef USE_CUBEMAP_PASS
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;
#endif
#else
#ifdef USES_HALF_RES_COLOR
- half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
+ half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
+ quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;
#endif
#endif
@@ -220,7 +220,7 @@ void main() {
}
- frag_color.rgb = color * params.position_multiplier.w;
+ frag_color.rgb = color;
frag_color.a = alpha;
#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS)
@@ -242,12 +242,13 @@ void main() {
#endif // DISABLE_FOG
- // Blending is disabled for Sky, so alpha doesn't blend
- // alpha is used for subsurface scattering so make sure it doesn't get applied to Sky
+ // Blending is disabled for Sky, so alpha doesn't blend.
+ // Alpha is used for subsurface scattering so make sure it doesn't get applied to Sky.
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
frag_color.a = 0.0;
}
- // For mobile renderer we're dividing by 2.0 as we're using a UNORM buffer
- frag_color.rgb = frag_color.rgb / params.luminance_multiplier;
+ // For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer.
+ // For both mobile and clustered, we also bake in the exposure value for the environment and camera.
+ frag_color.rgb = frag_color.rgb * params.luminance_multiplier;
}
diff --git a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
index 07d5223472..eed9038502 100644
--- a/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
@@ -84,6 +84,9 @@ struct VoxelGIData {
float normal_bias; // 4 - 88
bool blend_ambient; // 4 - 92
uint mipmaps; // 4 - 96
+
+ vec3 pad; // 12 - 108
+ float exposure_normalization; // 4 - 112
};
layout(set = 0, binding = 11, std140) uniform VoxelGIs {
@@ -105,6 +108,8 @@ struct SDFVoxelGICascadeData {
float to_probe;
ivec3 probe_world_offset;
float to_cell; // 1/bounds * grid_size
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 1, binding = 0, std140) uniform SDFGI {
@@ -624,7 +629,7 @@ void main() {
light += a * slight;
}
- light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject;
+ light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject * voxel_gi_instances.data[i].exposure_normalization;
total_light += light.rgb;
}
@@ -691,7 +696,7 @@ void main() {
vec3 ambient = texelFetch(sampler2DArray(sdfgi_ambient_texture, linear_sampler), uvw, 0).rgb;
- ambient_accum.rgb += ambient * weight;
+ ambient_accum.rgb += ambient * weight * sdfgi.cascades[i].exposure_normalization;
ambient_accum.a += weight;
}
diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
index a7fca25a6b..7488a3f2c7 100644
--- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
@@ -44,7 +44,7 @@ struct ReflectionData {
bool exterior;
bool box_project;
uint ambient_mode;
- uint pad;
+ float exposure_normalization;
//0-8 is intensity,8-9 is ambient, mode
highp mat4 local_matrix; // up to here for spot and omni, rest is for directional
// notes: for ambientblend, use distance to edge to blend between already existing global environment
@@ -52,7 +52,7 @@ struct ReflectionData {
struct DirectionalLightData {
mediump vec3 direction;
- mediump float energy;
+ highp float energy; // needs to be highp to avoid NaNs being created with high energy values (i.e. when using physical light units and over-exposing the image)
mediump vec3 color;
mediump float size;
mediump float specular;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
index 6b4e4a5a16..26b96b358f 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
@@ -986,6 +986,11 @@ void fragment_shader(in SceneData scene_data) {
vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
vec3 ambient_light = vec3(0.0, 0.0, 0.0);
+#ifndef MODE_UNSHADED
+ // Used in regular draw pass and when drawing SDFs for SDFGI and materials for VoxelGI.
+ emission *= scene_data.emissive_exposure_normalization;
+#endif
+
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
if (scene_data.use_reflection_cubemap) {
@@ -1015,6 +1020,7 @@ void fragment_shader(in SceneData scene_data) {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ specular_light *= scene_data.IBL_exposure_normalization;
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
@@ -1035,7 +1041,7 @@ void fragment_shader(in SceneData scene_data) {
#else
vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
-
+ cubemap_ambient *= scene_data.IBL_exposure_normalization;
ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
}
}
@@ -1094,15 +1100,16 @@ void fragment_shader(in SceneData scene_data) {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *
+ scene_data.emissive_exposure_normalization;
} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -1120,20 +1127,22 @@ void fragment_shader(in SceneData scene_data) {
uint idx = instances.data[instance_index].gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
+ float en = lightmaps.data[idx].exposure_normalization;
- ambient_light += lm_light_l0 * 0.282095f;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x;
+ ambient_light += lm_light_l0 * 0.282095f * en;
+ ambient_light += lm_light_l1n1 * 0.32573 * n.y * en;
+ ambient_light += lm_light_l1_0 * 0.32573 * n.z * en;
+ ambient_light += lm_light_l1p1 * 0.32573 * n.x * en;
if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y;
- specular_light += lm_light_l1_0 * 0.32573 * r.z;
- specular_light += lm_light_l1p1 * 0.32573 * r.x;
+ specular_light += lm_light_l1n1 * 0.32573 * r.y * en;
+ specular_light += lm_light_l1_0 * 0.32573 * r.z * en;
+ specular_light += lm_light_l1p1 * 0.32573 * r.x * en;
}
} else {
- ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
+ uint idx = instances.data[instance_index].gi_offset >> 20;
+ ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization;
}
}
#else
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
index f0717294ef..45484b8c47 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
@@ -105,6 +105,8 @@ directional_lights;
struct Lightmap {
mat3 normal_xform;
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
@@ -139,6 +141,8 @@ struct SDFVoxelGICascadeData {
float to_probe;
ivec3 probe_world_offset;
float to_cell; // 1/bounds * grid_size
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 0, binding = 15, std140) uniform SDFGI {
@@ -251,7 +255,8 @@ struct SceneData {
bool pancake_shadows;
vec2 taa_jitter;
- uvec2 pad2;
+ float emissive_exposure_normalization;
+ float IBL_exposure_normalization;
};
layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
@@ -340,6 +345,9 @@ struct VoxelGIData {
float normal_bias; // 4 - 88
bool blend_ambient; // 4 - 92
uint mipmaps; // 4 - 96
+
+ vec3 pad; // 12 - 108
+ float exposure_normalization; // 4 - 112
};
layout(set = 1, binding = 17, std140) uniform VoxelGIs {
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
index c88bd0a14b..ae5e1b7251 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
@@ -94,7 +94,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
light += cone_weights[i] * cone_light.rgb;
}
- light *= voxel_gi_instances.data[index].dynamic_range;
+ light *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
out_diff += vec4(light * blend, blend);
//irradiance
@@ -102,7 +102,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
if (voxel_gi_instances.data[index].blend_ambient) {
irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95));
}
- irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
//irr_light=vec3(0.0);
out_spec += vec4(irr_light.rgb * blend, blend);
@@ -189,7 +189,7 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
diffuse = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb;
- diffuse_accum += vec4(diffuse * weight, weight);
+ diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight);
if (use_specular) {
vec3 specular = vec3(0.0);
@@ -203,7 +203,7 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal
specular = mix(specular, textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb, (roughness - 0.5) * 2.0);
}
- specular_accum += specular * weight;
+ specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization;
}
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 7299bb0576..4e6e29b315 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -909,7 +909,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
vec4 reflection;
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier;
-
+ reflection.rgb *= reflections.data[ref_index].exposure_normalization;
if (reflections.data[ref_index].exterior) {
reflection.rgb = mix(specular_light, reflection.rgb, blend);
}
@@ -932,6 +932,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
vec4 ambient_out;
ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
+ ambient_out.rgb *= reflections.data[ref_index].exposure_normalization;
ambient_out.a = blend;
if (reflections.data[ref_index].exterior) {
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
index 0ffc72f78f..5a5ada7231 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
@@ -471,8 +471,10 @@ layout(location = 8) highp in float dp_clip;
#define model_matrix draw_call.transform
#ifdef USE_MULTIVIEW
#define projection_matrix scene_data.projection_matrix_view[ViewIndex]
+#define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex]
#else
#define projection_matrix scene_data.projection_matrix
+#define inv_projection_matrix scene_data.inv_projection_matrix
#endif
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
@@ -887,6 +889,11 @@ void main() {
vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
vec3 ambient_light = vec3(0.0, 0.0, 0.0);
+#ifndef MODE_UNSHADED
+ // Used in regular draw pass and when drawing SDFs for SDFGI and materials for VoxelGI.
+ emission *= scene_data.emissive_exposure_normalization;
+#endif
+
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
if (scene_data.use_reflection_cubemap) {
@@ -915,6 +922,8 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ specular_light *= sc_luminance_multiplier;
+ specular_light *= scene_data.IBL_exposure_normalization;
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
@@ -935,7 +944,8 @@ void main() {
#else
vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
-
+ cubemap_ambient *= sc_luminance_multiplier;
+ cubemap_ambient *= scene_data.IBL_exposure_normalization;
ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
}
}
@@ -993,15 +1003,16 @@ void main() {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *
+ scene_data.emissive_exposure_normalization;
} else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -1010,6 +1021,8 @@ void main() {
uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;
uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);
+ uint idx = draw_call.gi_offset >> 20;
+
if (uses_sh) {
uvw.z *= 4.0; //SH textures use 4 times more data
vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
@@ -1017,22 +1030,22 @@ void main() {
vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
- uint idx = draw_call.gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
+ float exposure_normalization = lightmaps.data[idx].exposure_normalization;
ambient_light += lm_light_l0 * 0.282095f;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x;
+ ambient_light += lm_light_l1n1 * 0.32573 * n.y * exposure_normalization;
+ ambient_light += lm_light_l1_0 * 0.32573 * n.z * exposure_normalization;
+ ambient_light += lm_light_l1p1 * 0.32573 * n.x * exposure_normalization;
if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y;
- specular_light += lm_light_l1_0 * 0.32573 * r.z;
- specular_light += lm_light_l1p1 * 0.32573 * r.x;
+ specular_light += lm_light_l1n1 * 0.32573 * r.y * exposure_normalization;
+ specular_light += lm_light_l1_0 * 0.32573 * r.z * exposure_normalization;
+ specular_light += lm_light_l1p1 * 0.32573 * r.x * exposure_normalization;
}
} else {
- ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
+ ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization;
}
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
index 98ad674ce0..3a9c52f5bc 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
@@ -94,6 +94,8 @@ directional_lights;
struct Lightmap {
mediump mat3 normal_xform;
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
@@ -187,8 +189,8 @@ struct SceneData {
mediump float reflection_multiplier; // one normally, zero when rendering reflections
bool pancake_shadows;
- uint pad1;
- uint pad2;
+ float emissive_exposure_normalization;
+ float IBL_exposure_normalization;
uint pad3;
};
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index b845c1155e..81b0661481 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -93,6 +93,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
+ light.param[RS::LIGHT_PARAM_INTENSITY] = p_type == RS::LIGHT_DIRECTIONAL ? 100000.0 : 1000.0;
light_owner.initialize_rid(p_light, light);
}
@@ -502,6 +503,13 @@ void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_
reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
+void LightStorage::reflection_probe_set_baked_exposure(RID p_probe, float p_exposure) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->baked_exposure = p_exposure;
+}
+
AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, AABB());
@@ -569,6 +577,13 @@ int LightStorage::reflection_probe_get_resolution(RID p_probe) const {
return reflection_probe->resolution;
}
+float LightStorage::reflection_probe_get_baked_exposure(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 1.0);
+
+ return reflection_probe->baked_exposure;
+}
+
float LightStorage::reflection_probe_get_intensity(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
@@ -711,6 +726,13 @@ void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedV
lm->tetrahedra = p_tetrahedra;
}
+void LightStorage::lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ lm->baked_exposure = p_exposure;
+}
+
PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, PackedVector3Array());
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 7e98a3cb8e..82d609291c 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -87,6 +87,7 @@ private:
bool enable_shadows = false;
uint32_t cull_mask = (1 << 20) - 1;
float mesh_lod_threshold = 0.01;
+ float baked_exposure = 1.0;
Dependency dependency;
};
@@ -99,6 +100,7 @@ private:
bool uses_spherical_harmonics = false;
bool interior = false;
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+ float baked_exposure = 1.0;
int32_t array_index = -1; //unassigned
PackedVector3Array points;
PackedColorArray point_sh;
@@ -279,6 +281,8 @@ public:
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+ void reflection_probe_set_baked_exposure(RID p_probe, float p_exposure);
+
virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
@@ -288,6 +292,7 @@ public:
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
int reflection_probe_get_resolution(RID p_probe) const;
+ float reflection_probe_get_baked_exposure(RID p_probe) const;
virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
float reflection_probe_get_intensity(RID p_probe) const;
@@ -311,6 +316,7 @@ public:
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
+ virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) override;
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
@@ -330,6 +336,11 @@ public:
ERR_FAIL_COND_V(!lm, RID());
return lm->light_texture;
}
+ _FORCE_INLINE_ float lightmap_get_baked_exposure_normalization(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, 1.0);
+ return lm->baked_exposure;
+ }
_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);