diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml
index fee48dd24625..ac612ccbd85d 100644
--- a/doc/classes/ReflectionProbe.xml
+++ b/doc/classes/ReflectionProbe.xml
@@ -11,6 +11,15 @@
$DOCS_URL/tutorials/3d/reflection_probes.html
+
+
+
+
+ Queues an update of the ReflectionProbe cubemap and ambient lighting. The update will not be visible immediately; it typically takes 6 frames for the update to be visible (since 1 cubemap face is rendered per frame). [method queue_update] should be called [i]after[/i] modifying nearby objects to ensure the reflection remains up-to-date.
+ [b]Note:[/b] [method queue_update] only has an effect when [member update_mode] is [constant UPDATE_ONCE].
+
+
+
The custom ambient color to use within the [ReflectionProbe]'s [member extents]. Only effective if [member ambient_mode] is [constant AMBIENT_COLOR].
@@ -58,7 +67,7 @@
- Update the probe once on the next frame (recommended for most objects). The corresponding radiance map will be generated over the following six frames. This takes more time to update than [constant UPDATE_ALWAYS], but it has a lower performance cost and can result in higher-quality reflections. The ReflectionProbe is updated when its transform changes, but not when nearby geometry changes. You can force a [ReflectionProbe] update by moving the [ReflectionProbe] slightly in any direction.
+ Update the probe once on the next frame (recommended for most cases). The corresponding radiance map will be generated over the following six frames. This takes more time to update than [constant UPDATE_ALWAYS], but it has a lower performance cost and can result in higher-quality reflections. The ReflectionProbe is updated when its transform changes, but not when nearby geometry changes. You can force a [ReflectionProbe] update using [method queue_update].
Update the probe every frame. This provides better results for fast-moving dynamic objects (such as cars). However, it has a significant performance cost. Due to the cost, it's recommended to only use one ReflectionProbe with [constant UPDATE_ALWAYS] at most per scene. For all other use cases, use [constant UPDATE_ONCE].
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 6aa923738557..93c75e95f2bd 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -2580,6 +2580,14 @@
To place in a scene, attach this reflection probe to an instance using [method instance_set_base] using the returned RID.
+
+
+
+
+ Queues an update of the reflection probe cubemap and ambient lighting. The update will not be visible immediately; it typically takes 6 frames for the update to be visible (since 1 cubemap face is rendered per frame). [method reflection_probe_queue_update] should be called [i]after[/i] modifying nearby objects to ensure the reflection remains up-to-date.
+ [b]Note:[/b] [method reflection_probe_queue_update] only has an effect when the update mode is [constant REFLECTION_PROBE_UPDATE_ONCE]. Equivalent to [method ReflectionProbe.queue_update].
+
+
diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp
index 6411590aee6d..041347f00b47 100644
--- a/drivers/gles3/storage/light_storage.cpp
+++ b/drivers/gles3/storage/light_storage.cpp
@@ -384,6 +384,9 @@ void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers
void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
}
+void LightStorage::reflection_probe_queue_update(RID p_probe) {
+}
+
AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
return AABB();
}
diff --git a/drivers/gles3/storage/light_storage.h b/drivers/gles3/storage/light_storage.h
index f054f0fdc634..7b01fab0f2c8 100644
--- a/drivers/gles3/storage/light_storage.h
+++ b/drivers/gles3/storage/light_storage.h
@@ -289,6 +289,8 @@ class LightStorage : public RendererLightStorage {
virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
+ virtual void reflection_probe_queue_update(RID p_probe) override;
+
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;
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index bc3cc31963c7..61164b06731a 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -171,6 +171,15 @@ ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const {
return update_mode;
}
+void ReflectionProbe::queue_update() {
+ // Queuing an update only makes sense when the update mode is set to Once.
+ if (update_mode != UPDATE_ONCE) {
+ return;
+ }
+
+ RS::get_singleton()->reflection_probe_queue_update(probe);
+}
+
AABB ReflectionProbe::get_aabb() const {
AABB aabb;
aabb.position = -origin_offset;
@@ -226,6 +235,8 @@ void ReflectionProbe::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &ReflectionProbe::set_update_mode);
ClassDB::bind_method(D_METHOD("get_update_mode"), &ReflectionProbe::get_update_mode);
+ ClassDB::bind_method(D_METHOD("queue_update"), &ReflectionProbe::queue_update);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "update_mode", PROPERTY_HINT_ENUM, "Once (Fast),Always (Slow)"), "set_update_mode", "get_update_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "intensity", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_intensity", "get_intensity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_distance", PROPERTY_HINT_RANGE, "0,16384,0.1,or_greater,exp,suffix:m"), "set_max_distance", "get_max_distance");
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index 5a5a3fe0bb74..c7848d0b1683 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -112,6 +112,8 @@ class ReflectionProbe : public VisualInstance3D {
void set_update_mode(UpdateMode p_mode);
UpdateMode get_update_mode() const;
+ void queue_update();
+
virtual AABB get_aabb() const override;
ReflectionProbe();
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index 79f484d51312..ab1689e6f805 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -102,6 +102,8 @@ class LightStorage : public RendererLightStorage {
virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override {}
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override { return 0.0; }
+ virtual void reflection_probe_queue_update(RID p_probe) override {}
+
virtual AABB reflection_probe_get_aabb(RID p_probe) const override { return AABB(); }
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; }
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override { return 0; }
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 81b0661481f2..3483b150773a 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -510,6 +510,13 @@ void LightStorage::reflection_probe_set_baked_exposure(RID p_probe, float p_expo
reflection_probe->baked_exposure = p_exposure;
}
+void LightStorage::reflection_probe_queue_update(RID p_probe) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
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());
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 82d609291c0f..803c6576f1b8 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -283,6 +283,8 @@ class LightStorage : public RendererLightStorage {
void reflection_probe_set_baked_exposure(RID p_probe, float p_exposure);
+ virtual void reflection_probe_queue_update(RID p_probe) override;
+
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;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index dfe16431bdd0..5c1870d81cd2 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -394,6 +394,7 @@ class RenderingServerDefault : public RenderingServer {
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
FUNC2(reflection_probe_set_resolution, RID, int)
FUNC2(reflection_probe_set_mesh_lod_threshold, RID, float)
+ FUNC1(reflection_probe_queue_update, RID)
/* LIGHTMAP */
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index b04bc671eef7..c253f817ac88 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -105,6 +105,8 @@ class RendererLightStorage {
virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0;
virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) = 0;
+ virtual void reflection_probe_queue_update(RID p_probe) = 0;
+
virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0;
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index cbcfc8fe49a9..c5fa62e6da89 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -1964,6 +1964,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask);
ClassDB::bind_method(D_METHOD("reflection_probe_set_resolution", "probe", "resolution"), &RenderingServer::reflection_probe_set_resolution);
ClassDB::bind_method(D_METHOD("reflection_probe_set_mesh_lod_threshold", "probe", "pixels"), &RenderingServer::reflection_probe_set_mesh_lod_threshold);
+ ClassDB::bind_method(D_METHOD("reflection_probe_queue_update", "probe"), &RenderingServer::reflection_probe_queue_update);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE);
BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 67ba407775ae..eb992cc480d3 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -542,6 +542,8 @@ class RenderingServer : public Object {
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0;
virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_pixels) = 0;
+ virtual void reflection_probe_queue_update(RID p_probe) = 0;
+
/* DECAL API */
enum DecalTexture {