summaryrefslogtreecommitdiffstats
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio/audio_stream.cpp6
-rw-r--r--servers/physics_2d/godot_area_2d.cpp16
-rw-r--r--servers/physics_2d/godot_body_2d.cpp10
-rw-r--r--servers/physics_2d/godot_physics_server_2d.cpp2
-rw-r--r--servers/physics_3d/godot_area_3d.cpp14
-rw-r--r--servers/physics_3d/godot_body_3d.cpp10
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp14
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp2
-rw-r--r--servers/rendering/dummy/environment/gi.h2
-rw-r--r--servers/rendering/dummy/rasterizer_canvas_dummy.h2
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h3
-rw-r--r--servers/rendering/environment/renderer_gi.h2
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp18
-rw-r--r--servers/rendering/renderer_canvas_cull.h7
-rw-r--r--servers/rendering/renderer_canvas_render.h5
-rw-r--r--servers/rendering/renderer_rd/effects/debug_effects.cpp4
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp5
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h4
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp85
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h17
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp11
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp155
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h17
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp13
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h1
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp51
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h6
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp42
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl47
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/forward_id_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp11
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp50
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h18
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h12
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp7
-rw-r--r--servers/rendering/renderer_scene_cull.cpp2
-rw-r--r--servers/rendering/renderer_viewport.cpp60
-rw-r--r--servers/rendering/rendering_server_default.h8
-rw-r--r--servers/rendering/shader_compiler.cpp6
-rw-r--r--servers/rendering/shader_language.cpp8
-rw-r--r--servers/rendering/shader_types.cpp6
-rw-r--r--servers/rendering/storage/particles_storage.h3
-rw-r--r--servers/rendering_server.cpp247
-rw-r--r--servers/rendering_server.h24
-rw-r--r--servers/text/text_server_extension.cpp13
-rw-r--r--servers/text/text_server_extension.h5
-rw-r--r--servers/text_server.cpp8
-rw-r--r--servers/text_server.h10
-rw-r--r--servers/xr_server.cpp4
59 files changed, 797 insertions, 310 deletions
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 455a8b49a1..65d88a0eba 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -810,7 +810,11 @@ void AudioStreamPlaybackRandomizer::tag_used_streams() {
int AudioStreamPlaybackRandomizer::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (playing.is_valid()) {
- return playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
+ int mixed_samples = playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
+ for (int samp = 0; samp < mixed_samples; samp++) {
+ p_buffer[samp] *= volume_scale;
+ }
+ return mixed_samples;
} else {
for (int i = 0; i < p_frames; i++) {
p_buffer[i] = AudioFrame(0, 0);
diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp
index 4d2148aa07..d6c786706c 100644
--- a/servers/physics_2d/godot_area_2d.cpp
+++ b/servers/physics_2d/godot_area_2d.cpp
@@ -78,13 +78,6 @@ void GodotArea2D::set_space(GodotSpace2D *p_space) {
}
void GodotArea2D::set_monitor_callback(const Callable &p_callback) {
- ObjectID id = p_callback.get_object_id();
-
- if (id == monitor_callback.get_object_id()) {
- monitor_callback = p_callback;
- return;
- }
-
_unregister_shapes();
monitor_callback = p_callback;
@@ -100,13 +93,6 @@ void GodotArea2D::set_monitor_callback(const Callable &p_callback) {
}
void GodotArea2D::set_area_monitor_callback(const Callable &p_callback) {
- ObjectID id = p_callback.get_object_id();
-
- if (id == area_monitor_callback.get_object_id()) {
- area_monitor_callback = p_callback;
- return;
- }
-
_unregister_shapes();
area_monitor_callback = p_callback;
@@ -194,7 +180,7 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const {
}
void GodotArea2D::_queue_monitor_update() {
- ERR_FAIL_COND(!get_space());
+ ERR_FAIL_NULL(get_space());
if (!monitor_query_list.in_list()) {
get_space()->area_add_to_monitor_query_list(&monitor_query_list);
diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp
index 4a7b470768..12c3e1e5b4 100644
--- a/servers/physics_2d/godot_body_2d.cpp
+++ b/servers/physics_2d/godot_body_2d.cpp
@@ -422,7 +422,7 @@ void GodotBody2D::integrate_forces(real_t p_step) {
return;
}
- ERR_FAIL_COND(!get_space());
+ ERR_FAIL_NULL(get_space());
int ac = areas.size();
@@ -615,7 +615,7 @@ void GodotBody2D::integrate_velocities(real_t p_step) {
return;
}
- if (fi_callback_data || body_state_callback.get_object()) {
+ if (fi_callback_data || body_state_callback.is_valid()) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@@ -676,7 +676,7 @@ void GodotBody2D::call_queries() {
Variant direct_state_variant = get_direct_state();
if (fi_callback_data) {
- if (!fi_callback_data->callable.get_object()) {
+ if (!fi_callback_data->callable.is_valid()) {
set_force_integration_callback(Callable());
} else {
const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
@@ -692,7 +692,7 @@ void GodotBody2D::call_queries() {
}
}
- if (body_state_callback.get_object()) {
+ if (body_state_callback.is_valid()) {
body_state_callback.call(direct_state_variant);
}
}
@@ -719,7 +719,7 @@ void GodotBody2D::set_state_sync_callback(const Callable &p_callable) {
}
void GodotBody2D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
- if (p_callable.get_object()) {
+ if (p_callable.is_valid()) {
if (!fi_callback_data) {
fi_callback_data = memnew(ForceIntegrationCallbackData);
}
diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp
index 112ba240b6..8df17992ea 100644
--- a/servers/physics_2d/godot_physics_server_2d.cpp
+++ b/servers/physics_2d/godot_physics_server_2d.cpp
@@ -994,7 +994,7 @@ void GodotPhysicsServer2D::body_set_pickable(RID p_body, bool p_pickable) {
bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
GodotBody2D *body = body_owner.get_or_null(p_body);
ERR_FAIL_NULL_V(body, false);
- ERR_FAIL_COND_V(!body->get_space(), false);
+ ERR_FAIL_NULL_V(body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
_update_shapes();
diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp
index 5bf16aa688..d0b287b058 100644
--- a/servers/physics_3d/godot_area_3d.cpp
+++ b/servers/physics_3d/godot_area_3d.cpp
@@ -87,12 +87,6 @@ void GodotArea3D::set_space(GodotSpace3D *p_space) {
}
void GodotArea3D::set_monitor_callback(const Callable &p_callback) {
- ObjectID id = p_callback.get_object_id();
- if (id == monitor_callback.get_object_id()) {
- monitor_callback = p_callback;
- return;
- }
-
_unregister_shapes();
monitor_callback = p_callback;
@@ -108,12 +102,6 @@ void GodotArea3D::set_monitor_callback(const Callable &p_callback) {
}
void GodotArea3D::set_area_monitor_callback(const Callable &p_callback) {
- ObjectID id = p_callback.get_object_id();
- if (id == area_monitor_callback.get_object_id()) {
- area_monitor_callback = p_callback;
- return;
- }
-
_unregister_shapes();
area_monitor_callback = p_callback;
@@ -223,7 +211,7 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const {
}
void GodotArea3D::_queue_monitor_update() {
- ERR_FAIL_COND(!get_space());
+ ERR_FAIL_NULL(get_space());
if (!monitor_query_list.in_list()) {
get_space()->area_add_to_monitor_query_list(&monitor_query_list);
diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp
index 21d5e49828..e102d0f3c9 100644
--- a/servers/physics_3d/godot_body_3d.cpp
+++ b/servers/physics_3d/godot_body_3d.cpp
@@ -477,7 +477,7 @@ void GodotBody3D::integrate_forces(real_t p_step) {
return;
}
- ERR_FAIL_COND(!get_space());
+ ERR_FAIL_NULL(get_space());
int ac = areas.size();
@@ -674,7 +674,7 @@ void GodotBody3D::integrate_velocities(real_t p_step) {
return;
}
- if (fi_callback_data || body_state_callback.get_object()) {
+ if (fi_callback_data || body_state_callback.is_valid()) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@@ -759,7 +759,7 @@ void GodotBody3D::call_queries() {
Variant direct_state_variant = get_direct_state();
if (fi_callback_data) {
- if (!fi_callback_data->callable.get_object()) {
+ if (!fi_callback_data->callable.is_valid()) {
set_force_integration_callback(Callable());
} else {
const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
@@ -771,7 +771,7 @@ void GodotBody3D::call_queries() {
}
}
- if (body_state_callback.get_object()) {
+ if (body_state_callback.is_valid()) {
body_state_callback.call(direct_state_variant);
}
}
@@ -798,7 +798,7 @@ void GodotBody3D::set_state_sync_callback(const Callable &p_callable) {
}
void GodotBody3D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
- if (p_callable.get_object()) {
+ if (p_callable.is_valid()) {
if (!fi_callback_data) {
fi_callback_data = memnew(ForceIntegrationCallbackData);
}
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index 4118a19f10..8a7b4e0f07 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -912,7 +912,7 @@ void GodotPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) {
bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) {
GodotBody3D *body = body_owner.get_or_null(p_body);
ERR_FAIL_NULL_V(body, false);
- ERR_FAIL_COND_V(!body->get_space(), false);
+ ERR_FAIL_NULL_V(body->get_space(), false);
ERR_FAIL_COND_V(body->get_space()->is_locked(), false);
_update_shapes();
@@ -1225,7 +1225,7 @@ void GodotPhysicsServer3D::joint_make_pin(RID p_joint, RID p_body_A, const Vecto
ERR_FAIL_NULL(body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
+ ERR_FAIL_NULL(body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
@@ -1297,7 +1297,7 @@ void GodotPhysicsServer3D::joint_make_hinge(RID p_joint, RID p_body_A, const Tra
ERR_FAIL_NULL(body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
+ ERR_FAIL_NULL(body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
@@ -1321,7 +1321,7 @@ void GodotPhysicsServer3D::joint_make_hinge_simple(RID p_joint, RID p_body_A, co
ERR_FAIL_NULL(body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
+ ERR_FAIL_NULL(body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
@@ -1422,7 +1422,7 @@ void GodotPhysicsServer3D::joint_make_slider(RID p_joint, RID p_body_A, const Tr
ERR_FAIL_NULL(body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
+ ERR_FAIL_NULL(body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
@@ -1462,7 +1462,7 @@ void GodotPhysicsServer3D::joint_make_cone_twist(RID p_joint, RID p_body_A, cons
ERR_FAIL_NULL(body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
+ ERR_FAIL_NULL(body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
@@ -1502,7 +1502,7 @@ void GodotPhysicsServer3D::joint_make_generic_6dof(RID p_joint, RID p_body_A, co
ERR_FAIL_NULL(body_A);
if (!p_body_B.is_valid()) {
- ERR_FAIL_COND(!body_A->get_space());
+ ERR_FAIL_NULL(body_A->get_space());
p_body_B = body_A->get_space()->get_static_global_body();
}
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 20b19ab243..0c2b935554 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -967,7 +967,7 @@ Vector3 GodotSoftBody3D::_compute_area_windforce(const GodotArea3D *p_area, cons
void GodotSoftBody3D::predict_motion(real_t p_delta) {
const real_t inv_delta = 1.0 / p_delta;
- ERR_FAIL_COND(!get_space());
+ ERR_FAIL_NULL(get_space());
bool gravity_done = false;
Vector3 gravity;
diff --git a/servers/rendering/dummy/environment/gi.h b/servers/rendering/dummy/environment/gi.h
index a26938c740..5d0e84ae43 100644
--- a/servers/rendering/dummy/environment/gi.h
+++ b/servers/rendering/dummy/environment/gi.h
@@ -78,6 +78,8 @@ public:
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override { return 0; }
+
+ virtual void sdfgi_reset() override {}
};
} // namespace RendererDummy
diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h
index 455a669277..862b941a73 100644
--- a/servers/rendering/dummy/rasterizer_canvas_dummy.h
+++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h
@@ -55,6 +55,8 @@ public:
bool free(RID p_rid) override { return true; }
void update() override {}
+ virtual void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) override {}
+
RasterizerCanvasDummy() {}
~RasterizerCanvasDummy() {}
};
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
index a40c96a8f5..33dad3f2f4 100644
--- a/servers/rendering/dummy/storage/particles_storage.h
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -47,6 +47,7 @@ public:
virtual void particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) override {}
virtual void particles_set_emitting(RID p_particles, bool p_emitting) override {}
virtual void particles_set_amount(RID p_particles, int p_amount) override {}
+ virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) override {}
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override {}
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override {}
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override {}
@@ -81,6 +82,8 @@ public:
virtual AABB particles_get_aabb(RID p_particles) const override { return AABB(); }
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override {}
+ virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) override {}
+ virtual void particles_set_interp_to_end(RID p_particles, float p_interp) override {}
virtual bool particles_get_emitting(RID p_particles) override { return false; }
virtual int particles_get_draw_passes(RID p_particles) const override { return 0; }
diff --git a/servers/rendering/environment/renderer_gi.h b/servers/rendering/environment/renderer_gi.h
index 6eff319882..94e2c1afda 100644
--- a/servers/rendering/environment/renderer_gi.h
+++ b/servers/rendering/environment/renderer_gi.h
@@ -79,6 +79,8 @@ public:
virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
virtual uint32_t voxel_gi_get_version(RID p_probe) const = 0;
+
+ virtual void sdfgi_reset() = 0;
};
#endif // RENDERER_GI_H
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index d6040e8820..c5206017f7 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -30,6 +30,7 @@
#include "renderer_canvas_cull.h"
+#include "core/config/project_settings.h"
#include "core/math/geometry_2d.h"
#include "renderer_viewport.h"
#include "rendering_server_default.h"
@@ -1557,6 +1558,11 @@ void RendererCanvasCull::canvas_item_clear(RID p_item) {
ERR_FAIL_NULL(canvas_item);
canvas_item->clear();
+#ifdef DEBUG_ENABLED
+ if (debug_redraw) {
+ canvas_item->debug_redraw_time = debug_redraw_time;
+ }
+#endif
}
void RendererCanvasCull::canvas_item_set_draw_index(RID p_item, int p_index) {
@@ -1612,6 +1618,15 @@ void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_
}
}
+void RendererCanvasCull::canvas_item_set_debug_redraw(bool p_enabled) {
+ debug_redraw = p_enabled;
+ RSG::canvas_render->set_debug_redraw(p_enabled, debug_redraw_time, debug_redraw_color);
+}
+
+bool RendererCanvasCull::canvas_item_get_debug_redraw() const {
+ return debug_redraw;
+}
+
void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_NULL(canvas_item);
@@ -2151,6 +2166,9 @@ RendererCanvasCull::RendererCanvasCull() {
z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *));
disable_scale = false;
+
+ debug_redraw_time = GLOBAL_DEF("debug/canvas_items/debug_redraw_time", 1.0);
+ debug_redraw_color = GLOBAL_DEF("debug/canvas_items/debug_redraw_color", Color(1.0, 0.2, 0.2, 0.5));
}
RendererCanvasCull::~RendererCanvasCull() {
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 4f11d2c7b1..0f51abbb26 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -174,6 +174,10 @@ public:
bool sdf_used = false;
bool snapping_2d_transforms_to_pixel = false;
+ bool debug_redraw = false;
+ double debug_redraw_time = 0;
+ Color debug_redraw_color;
+
PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator;
SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list;
@@ -260,6 +264,9 @@ public:
void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false);
+ void canvas_item_set_debug_redraw(bool p_enabled);
+ bool canvas_item_get_debug_redraw() const;
+
RID canvas_light_allocate();
void canvas_light_initialize(RID p_rid);
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index c30e53c29e..ef4de9ce54 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -358,6 +358,9 @@ public:
Command *last_command = nullptr;
Vector<CommandBlock> blocks;
uint32_t current_block;
+#ifdef DEBUG_ENABLED
+ mutable double debug_redraw_time = 0;
+#endif
template <class T>
T *alloc_command() {
@@ -517,6 +520,8 @@ public:
virtual bool free(RID p_rid) = 0;
virtual void update() = 0;
+ virtual void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) = 0;
+
RendererCanvasRender() { singleton = this; }
virtual ~RendererCanvasRender() {}
};
diff --git a/servers/rendering/renderer_rd/effects/debug_effects.cpp b/servers/rendering/renderer_rd/effects/debug_effects.cpp
index abcd9bbfae..3033d42375 100644
--- a/servers/rendering/renderer_rd/effects/debug_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/debug_effects.cpp
@@ -108,7 +108,7 @@ void DebugEffects::_create_frustum_arrays() {
// Create our index_array
PackedByteArray data;
- data.resize(6 * 2 * 3 * 4);
+ data.resize(6 * 2 * 3 * 2);
{
uint8_t *w = data.ptrw();
uint16_t *p16 = (uint16_t *)w;
@@ -142,7 +142,7 @@ void DebugEffects::_create_frustum_arrays() {
// Create our lines_array
PackedByteArray data;
- data.resize(12 * 2 * 4);
+ data.resize(12 * 2 * 2);
{
uint8_t *w = data.ptrw();
uint16_t *p16 = (uint16_t *)w;
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 0667ae87e5..dce8fadb63 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -392,6 +392,10 @@ Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const {
return &voxel_gi->dependency;
}
+void GI::sdfgi_reset() {
+ sdfgi_current_version++;
+}
+
////////////////////////////////////////////////////////////////////////////////
// SDFGI
@@ -416,6 +420,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
y_scale_mode = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_y_scale(p_env);
static const float y_scale[3] = { 2.0, 1.5, 1.0 };
y_mult = y_scale[y_scale_mode];
+ version = gi->sdfgi_current_version;
cascades.resize(num_cascades);
probe_axis_count = SDFGI::PROBE_DIVISOR + 1;
solid_cell_ratio = gi->sdfgi_solid_cell_ratio;
diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h
index 9a45919a2f..c46d4cbd25 100644
--- a/servers/rendering/renderer_rd/environment/gi.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -667,6 +667,7 @@ public:
float y_mult = 1.0;
+ uint32_t version = 0;
uint32_t render_pass = 0;
int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
@@ -701,11 +702,14 @@ public:
Vector3 sdfgi_debug_probe_dir;
bool sdfgi_debug_probe_enabled = false;
Vector3i sdfgi_debug_probe_index;
+ uint32_t sdfgi_current_version = 0;
/* SDFGI UPDATE */
int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
+ virtual void sdfgi_reset() override;
+
struct SDFGIData {
float grid_size[3];
uint32_t max_cascades;
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 efec3b5072..2397249ca5 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -1390,6 +1390,11 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
sdfgi->store_probes();
}
+ Size2i viewport_size = Size2i(1, 1);
+ if (rb.is_valid()) {
+ viewport_size = rb->get_internal_size();
+ }
+
p_render_data->cube_shadows.clear();
p_render_data->shadows.clear();
p_render_data->directional_shadows.clear();
@@ -1412,7 +1417,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
//cube shadows are rendered in their own way
for (const int &index : p_render_data->cube_shadows) {
- _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info);
+ _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size);
}
if (p_render_data->directional_shadows.size()) {
@@ -1442,11 +1447,11 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
//render directional shadows
for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info);
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, viewport_size);
}
//render positional shadows
for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info);
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, viewport_size);
}
_render_shadow_process();
@@ -1734,7 +1739,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_voxelgis(*p_render_data->voxel_gi_instances);
_setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
- _update_render_base_uniform_set(rb->get_samplers()); // May have changed due to the above (light buffer enlarged, as an example).
+ // May have changed due to the above (light buffer enlarged, as an example).
+ if (is_reflection_probe) {
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
+ } else {
+ _update_render_base_uniform_set(rb->get_samplers(), BASE_UNIFORM_SET_CACHE_VIEWPORT);
+ }
_fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_voxelgi, using_motion_pass);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
@@ -1965,7 +1975,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
p_render_data->scene_data->opaque_prepass_threshold = 0.0f;
// Shadow pass can change the base uniform set samplers.
- _update_render_base_uniform_set(rb->get_samplers());
+ if (is_reflection_probe) {
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
+ } else {
+ _update_render_base_uniform_set(rb->get_samplers(), BASE_UNIFORM_SET_CACHE_VIEWPORT);
+ }
_setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true, using_motion_pass);
@@ -2137,6 +2151,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_list_end();
}
+ if (rb_data.is_valid() && using_fsr2) {
+ // Make sure the upscaled texture is initialized, but not necessarily filled, before running screen copies
+ // so it properly detect if a dedicated copy texture should be used.
+ rb->ensure_upscaled();
+ }
+
if (scene_state.used_screen_texture) {
RENDER_TIMESTAMP("Copy Screen Texture");
@@ -2200,7 +2220,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (rb_data.is_valid() && (using_fsr2 || using_taa)) {
if (using_fsr2) {
- rb->ensure_upscaled();
rb_data->ensure_fsr2(fsr2_effect);
RID exposure;
@@ -2305,7 +2324,7 @@ void RenderForwardClustered::_render_buffers_debug_draw(const RenderDataRD *p_re
}
}
-void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) {
+void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
ERR_FAIL_COND(!light_storage->owns_light_instance(p_light));
@@ -2460,7 +2479,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas
if (render_cubemap) {
//rendering to cubemap
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_viewport_size);
if (finalize_cubemap) {
_render_shadow_process();
_render_shadow_end();
@@ -2478,20 +2497,20 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas
} else {
//render shadow
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info);
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_viewport_size);
}
}
void RenderForwardClustered::_render_shadow_begin() {
scene_state.shadow_passes.clear();
RD::get_singleton()->draw_command_begin_label("Shadow Setup");
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
render_list[RENDER_LIST_SECONDARY].clear();
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info) {
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -2515,7 +2534,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
render_data.instances = &p_instances;
render_data.render_info = p_render_info;
- _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, false, p_use_pancake, shadow_pass_index);
+ _setup_environment(&render_data, true, p_viewport_size, !p_flip_y, Color(), false, false, p_use_pancake, shadow_pass_index);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
scene_data.screen_mesh_lod_threshold = 0.0;
@@ -2609,7 +2628,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
_setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false, false);
@@ -2655,7 +2674,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
scene_shader.enable_advanced_shader_group();
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -2706,7 +2725,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance
scene_shader.enable_advanced_shader_group();
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -2775,7 +2794,7 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
PassMode pass_mode = PASS_MODE_SDF;
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
@@ -2849,21 +2868,23 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_bu
}
void RenderForwardClustered::base_uniforms_changed() {
- if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
- RD::get_singleton()->free(render_base_uniform_set);
+ for (int i = 0; i < BASE_UNIFORM_SET_CACHE_MAX; i++) {
+ if (!render_base_uniform_set_cache[i].is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set_cache[i])) {
+ RD::get_singleton()->free(render_base_uniform_set_cache[i]);
+ }
+ render_base_uniform_set_cache[i] = RID();
}
- render_base_uniform_set = RID();
}
-void RenderForwardClustered::_update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers) {
+void RenderForwardClustered::_update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers, BaseUniformSetCache p_cache_index) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version())) {
- if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
- RD::get_singleton()->free(render_base_uniform_set);
+ if (render_base_uniform_set_cache[p_cache_index].is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set_cache[p_cache_index]) || (lightmap_texture_array_version_cache[p_cache_index] != light_storage->lightmap_array_get_version())) {
+ if (render_base_uniform_set_cache[p_cache_index].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set_cache[p_cache_index])) {
+ RD::get_singleton()->free(render_base_uniform_set_cache[p_cache_index]);
}
- lightmap_texture_array_version = light_storage->lightmap_array_get_version();
+ lightmap_texture_array_version_cache[p_cache_index] = light_storage->lightmap_array_get_version();
Vector<RD::Uniform> uniforms;
@@ -3020,8 +3041,9 @@ void RenderForwardClustered::_update_render_base_uniform_set(const RendererRD::M
uniforms.append_array(p_samplers.get_uniforms(SAMPLERS_BINDING_FIRST_INDEX));
- render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET);
+ render_base_uniform_set_cache[p_cache_index] = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET);
}
+ render_base_uniform_set = render_base_uniform_set_cache[p_cache_index];
}
RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
@@ -3481,14 +3503,18 @@ void RenderForwardClustered::sdfgi_update(const Ref<RenderSceneBuffers> &p_rende
}
bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment);
+ bool needs_reset = sdfgi.is_valid() ? sdfgi->version != gi.sdfgi_current_version : false;
- if (!needs_sdfgi) {
+ if (!needs_sdfgi || needs_reset) {
if (sdfgi.is_valid()) {
// delete it
sdfgi.unref();
rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
}
- return;
+
+ if (!needs_sdfgi) {
+ return;
+ }
}
// Ensure advanced shaders are available if SDFGI is used.
@@ -3693,6 +3719,11 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->sort.priority = p_material->priority;
sdcache->sort.uses_projector = ginstance->using_projectors;
sdcache->sort.uses_softshadow = ginstance->using_softshadows;
+
+ uint64_t format = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_format(sdcache->surface);
+ if (p_material->shader_data->uses_tangent && !(format & RS::ARRAY_FORMAT_TANGENT)) {
+ WARN_PRINT_ED("Attempting to use a shader that requires tangents with a mesh that doesn't contain tangents. Ensure that meshes are imported with the 'ensure_tangents' option. If creating your own meshes, add an `ARRAY_TANGENT` array (when using ArrayMesh) or call `generate_tangents()` (when using SurfaceTool).");
+ }
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
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 46deb30cde..bedf119210 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -158,11 +158,20 @@ class RenderForwardClustered : public RendererSceneRenderRD {
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
+ enum BaseUniformSetCache {
+ BASE_UNIFORM_SET_CACHE_VIEWPORT,
+ BASE_UNIFORM_SET_CACHE_DEFAULT,
+ BASE_UNIFORM_SET_CACHE_MAX
+ };
+
RID render_base_uniform_set;
+ // One for custom samplers, one for default samplers.
+ // Need to switch between them as default is needed for probes, shadows, materials, etc.
+ RID render_base_uniform_set_cache[BASE_UNIFORM_SET_CACHE_MAX];
- uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
+ uint64_t lightmap_texture_array_version_cache[BASE_UNIFORM_SET_CACHE_MAX] = { 0xFFFFFFFF, 0xFFFFFFFF };
- void _update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers);
+ void _update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers, BaseUniformSetCache p_cache_index);
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
@@ -593,9 +602,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
/* Render shadows */
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1));
void _render_shadow_begin();
- void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1));
void _render_shadow_process();
void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL_BARRIERS);
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 9676474a66..5134f4d545 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -65,6 +65,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
uses_discard = false;
uses_roughness = false;
uses_normal = false;
+ uses_tangent = false;
+ bool uses_normal_map = false;
bool wireframe = false;
unshaded = false;
@@ -121,11 +123,16 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
- actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
+ actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal_map;
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
+ actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
+ actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY_FLOW"] = &uses_tangent;
+
actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection;
actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
@@ -150,6 +157,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
uses_normal_texture = gen_code.uses_normal_roughness_texture;
uses_vertex_time = gen_code.uses_vertex_time;
uses_fragment_time = gen_code.uses_fragment_time;
+ uses_normal |= uses_normal_map;
+ uses_tangent |= uses_normal_map;
#if 0
print_line("**compiling shader:");
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 0739cd9f86..3b83b2b582 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -165,6 +165,7 @@ public:
bool uses_discard = false;
bool uses_roughness = false;
bool uses_normal = false;
+ bool uses_tangent = false;
bool uses_particle_trails = false;
bool unshaded = false;
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 8a672d8628..462fc4b524 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -53,6 +53,7 @@ RendererRD::ForwardID RenderForwardMobile::ForwardIDStorageMobile::allocate_forw
index = forward_id_allocators[p_type].allocations.size();
forward_id_allocators[p_type].allocations.push_back(true);
forward_id_allocators[p_type].map.push_back(0xFF);
+ forward_id_allocators[p_type].last_pass.push_back(0);
} else {
forward_id_allocators[p_type].allocations[index] = true;
}
@@ -64,44 +65,72 @@ void RenderForwardMobile::ForwardIDStorageMobile::free_forward_id(RendererRD::Fo
forward_id_allocators[p_type].allocations[p_id] = false;
}
-void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) {
+void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index, uint64_t p_last_pass) {
forward_id_allocators[p_type].map[p_id] = p_index;
+ forward_id_allocators[p_type].last_pass[p_id] = p_last_pass;
}
void RenderForwardMobile::fill_push_constant_instance_indices(SceneState::InstanceData *p_instance_data, const GeometryInstanceForwardMobile *p_instance) {
- // First zero out our indices.
+ uint64_t current_frame = RSG::rasterizer->get_frame_number();
p_instance_data->omni_lights[0] = 0xFFFFFFFF;
p_instance_data->omni_lights[1] = 0xFFFFFFFF;
- p_instance_data->spot_lights[0] = 0xFFFFFFFF;
- p_instance_data->spot_lights[1] = 0xFFFFFFFF;
-
- p_instance_data->decals[0] = 0xFFFFFFFF;
- p_instance_data->decals[1] = 0xFFFFFFFF;
-
- p_instance_data->reflection_probes[0] = 0xFFFFFFFF;
- p_instance_data->reflection_probes[1] = 0xFFFFFFFF;
-
- for (uint32_t i = 0; i < MAX_RDL_CULL; i++) {
- uint32_t ofs = i < 4 ? 0 : 1;
- uint32_t shift = (i & 0x3) << 3;
+ uint32_t idx = 0;
+ for (uint32_t i = 0; i < p_instance->omni_light_count; i++) {
+ uint32_t ofs = idx < 4 ? 0 : 1;
+ uint32_t shift = (idx & 0x3) << 3;
uint32_t mask = ~(0xFF << shift);
- if (i < p_instance->omni_light_count) {
+
+ if (forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT].last_pass[p_instance->omni_lights[i]] == current_frame) {
p_instance_data->omni_lights[ofs] &= mask;
p_instance_data->omni_lights[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift;
+ idx++;
}
- if (i < p_instance->spot_light_count) {
+ }
+
+ p_instance_data->spot_lights[0] = 0xFFFFFFFF;
+ p_instance_data->spot_lights[1] = 0xFFFFFFFF;
+
+ idx = 0;
+ for (uint32_t i = 0; i < p_instance->spot_light_count; i++) {
+ uint32_t ofs = idx < 4 ? 0 : 1;
+ uint32_t shift = (idx & 0x3) << 3;
+ uint32_t mask = ~(0xFF << shift);
+ if (forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT].last_pass[p_instance->spot_lights[i]] == current_frame) {
p_instance_data->spot_lights[ofs] &= mask;
p_instance_data->spot_lights[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift;
+ idx++;
}
- if (i < p_instance->decals_count) {
+ }
+
+ p_instance_data->decals[0] = 0xFFFFFFFF;
+ p_instance_data->decals[1] = 0xFFFFFFFF;
+
+ idx = 0;
+ for (uint32_t i = 0; i < p_instance->decals_count; i++) {
+ uint32_t ofs = idx < 4 ? 0 : 1;
+ uint32_t shift = (idx & 0x3) << 3;
+ uint32_t mask = ~(0xFF << shift);
+ if (forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_DECAL].last_pass[p_instance->decals[i]] == current_frame) {
p_instance_data->decals[ofs] &= mask;
p_instance_data->decals[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift;
+ idx++;
}
- if (i < p_instance->reflection_probe_count) {
+ }
+
+ p_instance_data->reflection_probes[0] = 0xFFFFFFFF;
+ p_instance_data->reflection_probes[1] = 0xFFFFFFFF;
+
+ idx = 0;
+ for (uint32_t i = 0; i < p_instance->reflection_probe_count; i++) {
+ uint32_t ofs = idx < 4 ? 0 : 1;
+ uint32_t shift = (idx & 0x3) << 3;
+ uint32_t mask = ~(0xFF << shift);
+ if (forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].last_pass[p_instance->reflection_probes[i]] == current_frame) {
p_instance_data->reflection_probes[ofs] &= mask;
p_instance_data->reflection_probes[ofs] |= uint32_t(forward_id_storage_mobile->forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift;
+ idx++;
}
}
}
@@ -235,7 +264,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
RID render_target = render_buffers->get_render_target();
ERR_FAIL_COND_V(render_target.is_null(), RID());
RID target_buffer;
- if (texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) {
+ if (view_count > 1 || texture_storage->render_target_get_msaa(render_target) == RS::VIEWPORT_MSAA_DISABLED) {
target_buffer = texture_storage->render_target_get_rd_texture(render_target);
} else {
target_buffer = texture_storage->render_target_get_rd_texture_msaa(render_target);
@@ -539,7 +568,6 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co
void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
p_render_data->cube_shadows.clear();
p_render_data->shadows.clear();
@@ -598,28 +626,11 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
//full barrier here, we need raster, transfer and compute and it depends from the previous work
RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL_BARRIERS, RD::BARRIER_MASK_ALL_BARRIERS);
-
- bool using_shadows = true;
-
- if (p_render_data->reflection_probe.is_valid()) {
- if (!RSG::light_storage->reflection_probe_renders_shadows(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
- using_shadows = false;
- }
- } else {
- //do not render reflections when rendering a reflection probe
- light_storage->update_reflection_probe_buffer(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment);
- }
-
- uint32_t directional_light_count = 0;
- uint32_t positional_light_count = 0;
- light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
- texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform);
-
- p_render_data->directional_light_count = directional_light_count;
}
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
ERR_FAIL_NULL(p_render_data);
@@ -668,6 +679,25 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
bool using_subpass_transparent = true;
bool using_subpass_post_process = true;
+ bool using_shadows = true;
+
+ if (p_render_data->reflection_probe.is_valid()) {
+ if (!RSG::light_storage->reflection_probe_renders_shadows(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ using_shadows = false;
+ }
+ } else {
+ //do not render reflections when rendering a reflection probe
+ light_storage->update_reflection_probe_buffer(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment);
+ }
+
+ // Update light and decal buffer first so we know what lights and decals are safe to pair with.
+ uint32_t directional_light_count = 0;
+ uint32_t positional_light_count = 0;
+ light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
+ texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform);
+
+ p_render_data->directional_light_count = directional_light_count;
+
// fill our render lists early so we can find out if we use various features
_fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
@@ -733,7 +763,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform);
_setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
- _update_render_base_uniform_set(rb->get_samplers()); //may have changed due to the above (light buffer enlarged, as an example)
+ // May have changed due to the above (light buffer enlarged, as an example).
+ if (is_reflection_probe) {
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
+ } else {
+ _update_render_base_uniform_set(rb->get_samplers(), BASE_UNIFORM_SET_CACHE_VIEWPORT);
+ }
RD::get_singleton()->draw_command_end_label(); // Render Setup
@@ -872,7 +907,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
// Shadow pass can change the base uniform set samplers.
- _update_render_base_uniform_set(rb->get_samplers());
+ if (is_reflection_probe) {
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
+ } else {
+ _update_render_base_uniform_set(rb->get_samplers(), BASE_UNIFORM_SET_CACHE_VIEWPORT);
+ }
_setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, p_render_data->render_buffers.is_valid());
@@ -1234,7 +1273,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i
void RenderForwardMobile::_render_shadow_begin() {
scene_state.shadow_passes.clear();
RD::get_singleton()->draw_command_begin_label("Shadow Setup");
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
render_list[RENDER_LIST_SECONDARY].clear();
}
@@ -1341,7 +1380,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
RenderSceneDataRD scene_data;
scene_data.cam_projection = p_cam_projection;
@@ -1392,7 +1431,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
RD::get_singleton()->draw_command_begin_label("Render UV2");
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
RenderSceneDataRD scene_data;
scene_data.dual_paraboloid_side = 0;
@@ -1466,7 +1505,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
- _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default());
+ _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), BASE_UNIFORM_SET_CACHE_DEFAULT);
RenderSceneDataRD scene_data;
scene_data.cam_projection = p_cam_projection;
@@ -1504,23 +1543,23 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
}
void RenderForwardMobile::base_uniforms_changed() {
- if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
- RD::get_singleton()->free(render_base_uniform_set);
+ for (int i = 0; i < BASE_UNIFORM_SET_CACHE_MAX; i++) {
+ if (!render_base_uniform_set_cache[i].is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set_cache[i])) {
+ RD::get_singleton()->free(render_base_uniform_set_cache[i]);
+ }
+ render_base_uniform_set_cache[i] = RID();
}
- render_base_uniform_set = RID();
}
-void RenderForwardMobile::_update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers) {
+void RenderForwardMobile::_update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers, BaseUniformSetCache p_cache_index) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version())) {
- if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
- RD::get_singleton()->free(render_base_uniform_set);
+ if (render_base_uniform_set_cache[p_cache_index].is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set_cache[p_cache_index]) || (lightmap_texture_array_version_cache[p_cache_index] != light_storage->lightmap_array_get_version())) {
+ if (render_base_uniform_set_cache[p_cache_index].is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set_cache[p_cache_index])) {
+ RD::get_singleton()->free(render_base_uniform_set_cache[p_cache_index]);
}
- // This is all loaded into set 0
-
- lightmap_texture_array_version = light_storage->lightmap_array_get_version();
+ lightmap_texture_array_version_cache[p_cache_index] = light_storage->lightmap_array_get_version();
Vector<RD::Uniform> uniforms;
@@ -1669,8 +1708,9 @@ void RenderForwardMobile::_update_render_base_uniform_set(const RendererRD::Mate
uniforms.append_array(p_samplers.get_uniforms(SAMPLERS_BINDING_FIRST_INDEX));
- render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET);
+ render_base_uniform_set_cache[p_cache_index] = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET);
}
+ render_base_uniform_set = render_base_uniform_set_cache[p_cache_index];
}
RID RenderForwardMobile::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
@@ -2478,6 +2518,11 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->sort.geometry_id = p_mesh.get_local_index();
// sdcache->sort.uses_forward_gi = ginstance->can_sdfgi;
sdcache->sort.priority = p_material->priority;
+
+ uint64_t format = RendererRD::MeshStorage::get_singleton()->mesh_surface_get_format(sdcache->surface);
+ if (p_material->shader_data->uses_tangent && !(format & RS::ARRAY_FORMAT_TANGENT)) {
+ WARN_PRINT_ED("Attempting to use a shader that requires tangents with a mesh that doesn't contain tangents. Ensure that meshes are imported with the 'ensure_tangents' option. If creating your own meshes, add an `ARRAY_TANGENT` array (when using ArrayMesh) or call `generate_tangents()` (when using SurfaceTool).");
+ }
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh) {
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 50bf83b612..f10d3c1568 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -198,9 +198,19 @@ private:
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
void _pre_opaque_render(RenderDataRD *p_render_data);
- uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
+ enum BaseUniformSetCache {
+ BASE_UNIFORM_SET_CACHE_VIEWPORT,
+ BASE_UNIFORM_SET_CACHE_DEFAULT,
+ BASE_UNIFORM_SET_CACHE_MAX
+ };
+
+ // One for custom samplers, one for default samplers.
+ // Need to switch between them as default is needed for probes, shadows, materials, etc.
+ RID render_base_uniform_set_cache[BASE_UNIFORM_SET_CACHE_MAX];
+
+ uint64_t lightmap_texture_array_version_cache[BASE_UNIFORM_SET_CACHE_MAX] = { 0xFFFFFFFF, 0xFFFFFFFF };
- void _update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers);
+ void _update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers, BaseUniformSetCache p_cache_index);
void _update_instance_data_buffer(RenderListType p_render_list);
void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
@@ -535,6 +545,7 @@ protected:
struct ForwardIDAllocator {
LocalVector<bool> allocations;
LocalVector<uint8_t> map;
+ LocalVector<uint64_t> last_pass;
};
ForwardIDAllocator forward_id_allocators[RendererRD::FORWARD_ID_MAX];
@@ -542,7 +553,7 @@ protected:
public:
virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) override;
virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) override;
- virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) override;
+ virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index, uint64_t p_last_pass) override;
virtual bool uses_forward_ids() const override { return true; }
};
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 9a3556ce35..f1cec0e07c 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -67,6 +67,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uses_discard = false;
uses_roughness = false;
uses_normal = false;
+ uses_tangent = false;
+ bool uses_normal_map = false;
bool wireframe = false;
unshaded = false;
@@ -122,7 +124,12 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
- actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
+ actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal_map;
+
+ actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
+ actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY"] = &uses_tangent;
+ actions.usage_flag_pointers["ANISOTROPY_FLOW"] = &uses_tangent;
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
@@ -150,6 +157,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uses_screen_texture = gen_code.uses_screen_texture;
uses_depth_texture = gen_code.uses_depth_texture;
uses_normal_texture = gen_code.uses_normal_roughness_texture;
+ uses_normal |= uses_normal_map;
+ uses_tangent |= uses_normal_map;
#ifdef DEBUG_ENABLED
if (uses_sss) {
@@ -621,7 +630,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
actions.global_buffer_array_variable = "global_shader_uniforms.data";
- actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
+ actions.instance_uniform_index_variable = "instances.data[draw_call.instance_index].instance_uniforms_ofs";
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
actions.check_multiview_samplers = RendererCompositorRD::get_singleton()->is_xr_enabled(); // Make sure we check sampling multiview textures.
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index 5c76d89247..da189c6f67 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -119,6 +119,7 @@ public:
bool uses_discard = false;
bool uses_roughness = false;
bool uses_normal = false;
+ bool uses_tangent = false;
bool uses_particle_trails = false;
bool unshaded = false;
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index 2f1e79b397..0ebebd0540 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -38,7 +38,7 @@ class PipelineCacheRD {
SpinLock spin_lock;
RID shader;
- uint32_t input_mask;
+ uint64_t input_mask;
RD::RenderPrimitive render_primitive;
RD::PipelineRasterizationState rasterization_state;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 885a00856e..0b1561939e 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -485,7 +485,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
continue;
}
- push_constant.flags = base_flags | (push_constant.flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config
+ push_constant.flags = base_flags | (push_constant.flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); // Reset on each command for safety, keep canvastexture binding config.
switch (c->type) {
case Item::Command::TYPE_RECT: {
@@ -957,7 +957,48 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
c = c->next;
}
+#ifdef DEBUG_ENABLED
+ if (debug_redraw && p_item->debug_redraw_time > 0.0) {
+ Color dc = debug_redraw_color;
+ dc.a *= p_item->debug_redraw_time / debug_redraw_time;
+ RID pipeline = pipeline_variants->variants[PIPELINE_LIGHT_MODE_DISABLED][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
+
+ //bind textures
+
+ _bind_canvas_texture(p_draw_list, RID(), current_filter, current_repeat, last_texture, push_constant, texpixel_size);
+
+ Rect2 src_rect;
+ Rect2 dst_rect;
+
+ dst_rect = Rect2(Vector2(), p_item->rect.size);
+ src_rect = Rect2(0, 0, 1, 1);
+
+ push_constant.modulation[0] = dc.r;
+ push_constant.modulation[1] = dc.g;
+ push_constant.modulation[2] = dc.b;
+ push_constant.modulation[3] = dc.a;
+
+ push_constant.src_rect[0] = src_rect.position.x;
+ push_constant.src_rect[1] = src_rect.position.y;
+ push_constant.src_rect[2] = src_rect.size.width;
+ push_constant.src_rect[3] = src_rect.size.height;
+
+ push_constant.dst_rect[0] = dst_rect.position.x;
+ push_constant.dst_rect[1] = dst_rect.position.y;
+ push_constant.dst_rect[2] = dst_rect.size.width;
+ push_constant.dst_rect[3] = dst_rect.size.height;
+
+ RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant));
+ RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array);
+ RD::get_singleton()->draw_list_draw(p_draw_list, true);
+
+ p_item->debug_redraw_time -= RSG::rasterizer->get_frame_delta_time();
+
+ RenderingServerDefault::redraw_request();
+ }
+#endif
if (current_clip && reclip) {
//will make it re-enable clipping if needed afterwards
current_clip = nullptr;
@@ -2718,7 +2759,7 @@ bool RendererCanvasRenderRD::free(RID p_rid) {
}
void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) {
- p_size = nearest_power_of_2_templated(p_size);
+ p_size = MAX(1, nearest_power_of_2_templated(p_size));
if (p_size == state.shadow_texture_size) {
return;
}
@@ -2742,6 +2783,12 @@ void RendererCanvasRenderRD::set_shadow_texture_size(int p_size) {
}
}
+void RendererCanvasRenderRD::set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) {
+ debug_redraw = p_enabled;
+ debug_redraw_time = p_time;
+ debug_redraw_color = p_color;
+}
+
RendererCanvasRenderRD::~RendererCanvasRenderRD() {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
//canvas state
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 4c8cbd1c9f..7dbcd903e6 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -418,6 +418,10 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID _create_base_uniform_set(RID p_to_render_target, bool p_backbuffer);
+ bool debug_redraw = false;
+ Color debug_redraw_color;
+ double debug_redraw_time = 1.0;
+
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data = false); //recursive, so regular inline used instead.
void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *&current_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used);
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false);
@@ -450,6 +454,8 @@ public:
virtual void set_shadow_texture_size(int p_size);
+ void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color);
+
void set_time(double p_time);
void update();
bool free(RID p_rid);
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 07d56eae0c..1a33f1d6e0 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -260,15 +260,29 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
RD::get_singleton()->draw_command_begin_label("Copy screen texture");
- rb->allocate_blur_textures();
-
+ StringName texture_name;
bool can_use_storage = _render_buffers_can_be_storage();
Size2i size = rb->get_internal_size();
+ // When upscaling, the blur texture needs to be at the target size for post-processing to work. We prefer to use a
+ // dedicated backbuffer copy texture instead if the blur texture is not an option so shader effects work correctly.
+ Size2i target_size = rb->get_target_size();
+ bool internal_size_matches = (size.width == target_size.width) && (size.height == target_size.height);
+ bool reuse_blur_texture = !rb->has_upscaled_texture() || internal_size_matches;
+ if (reuse_blur_texture) {
+ rb->allocate_blur_textures();
+ texture_name = RB_TEX_BLUR_0;
+ } else {
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ usage_bits |= can_use_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR, rb->get_base_data_format(), usage_bits);
+ texture_name = RB_TEX_BACK_COLOR;
+ }
+
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
RID texture = rb->get_internal_texture(v);
- int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0).mipmaps);
- RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, 0);
+ int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, texture_name).mipmaps);
+ RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, texture_name, v, 0);
if (can_use_storage) {
copy_effects->copy_to_rect(texture, dest, Rect2i(0, 0, size.x, size.y));
@@ -279,8 +293,8 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
for (int i = 1; i < mipmaps; i++) {
RID source = dest;
- dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
- Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, i);
+ dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, texture_name, v, i);
+ Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, texture_name, i);
if (can_use_storage) {
copy_effects->make_mipmap(source, dest, msize);
@@ -351,6 +365,8 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RID color_texture = use_upscaled_texture ? rb->get_upscaled_texture() : rb->get_internal_texture();
Size2i color_size = use_upscaled_texture ? target_size : rb->get_internal_size();
+ bool dest_is_msaa_2d = rb->get_view_count() == 1 && texture_storage->render_target_get_msaa(render_target) != RS::VIEWPORT_MSAA_DISABLED;
+
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");
@@ -567,7 +583,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// If we do a bilinear upscale we just render into our render target and our shader will upscale automatically.
// Target size in this case is lying as we never get our real target size communicated.
// Bit nasty but...
- dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
+
+ if (dest_is_msaa_2d) {
+ dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
+ } else {
+ dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
+ }
}
tone_mapper->tonemapper(color_texture, dest_fb, tonemap);
@@ -585,6 +606,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
fsr->fsr_upscale(rb, source_texture, dest_texture);
}
+ if (dest_is_msaa_2d) {
+ // We can't upscale directly into our MSAA buffer so we need to do a copy
+ RID source_texture = texture_storage->render_target_get_rd_texture(render_target);
+ RID dest_fb = FramebufferCacheRD::get_singleton()->get_cache(texture_storage->render_target_get_rd_texture_msaa(render_target));
+ copy_effects->copy_to_fb_rect(source_texture, dest_fb, Rect2i(Point2i(), rb->get_target_size()));
+ }
+
RD::get_singleton()->draw_command_end_label();
}
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 10e37c7da8..242b0301f1 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -480,6 +480,7 @@ void ShaderRD::_save_to_cache(Version *p_version, int p_group) {
}
void ShaderRD::_allocate_placeholders(Version *p_version, int p_group) {
+ ERR_FAIL_NULL(p_version->variants);
for (uint32_t i = 0; i < group_to_variant_map[p_group].size(); i++) {
int variant_id = group_to_variant_map[p_group][i];
RID shader = RD::get_singleton()->shader_create_placeholder();
diff --git a/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
index 7b3c2f1c3b..6c77ab4a91 100644
--- a/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
@@ -33,7 +33,7 @@ layout(location = 0) out vec2 uv_interp;
void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
- uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0
+ uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0 * float(params.face_size); // saturate(x) * 2.0
}
/* clang-format off */
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
index 1e01d94533..fecf70bd01 100644
--- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
@@ -184,7 +184,7 @@ void main() {
vec4 test_normal_roughness = imageLoad(source_normal_roughness, test_pos);
vec3 test_normal = test_normal_roughness.xyz * 2.0 - 1.0;
test_normal = normalize(test_normal);
- test_normal.y = -test_normal.y; //because this code reads flipped
+ test_normal.y = -test_normal.y; // Because this code reads flipped.
if (dot(ray_dir, test_normal) < 0.001) {
// if depth was surpassed
@@ -203,6 +203,7 @@ void main() {
if (found) {
float margin_blend = 1.0;
+ vec2 final_pos = pos;
vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.05); // make a uniform margin
if (any(bvec4(lessThan(pos, vec2(0.0, 0.0)), greaterThan(pos, params.screen_size)))) {
@@ -219,16 +220,40 @@ void main() {
//margin_blend = 1.0;
}
- vec2 final_pos;
+ // Fade In / Fade Out
float grad = (steps_taken + 1.0) / float(params.num_steps);
float initial_fade = params.curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), params.curve_fade_in);
float fade = pow(clamp(1.0 - grad, 0.0, 1.0), params.distance_fade) * initial_fade;
+
+ // Ensure that precision errors do not introduce any fade. Even if it is just slightly below 1.0,
+ // strong specular light can leak through the reflection.
+ if (fade > 0.999) {
+ fade = 1.0;
+ }
+
// This is an ad-hoc term to fade out the SSR as roughness increases. Values used
// are meant to match the visual appearance of a ReflectionProbe.
float roughness_fade = smoothstep(0.4, 0.7, 1.0 - normal_roughness.w);
- final_pos = pos;
- vec4 final_color;
+ // Schlick term.
+ float metallic = texelFetch(source_metallic, ssC << 1, 0).w;
+
+ // F0 is the reflectance of normally incident light (perpendicular to the surface).
+ // Dielectric materials have a widely accepted default value of 0.04. We assume that metals reflect all light, so their F0 is 1.0.
+ float f0 = mix(0.04, 1.0, metallic);
+ float m = clamp(1.0 - dot(normal, -view_dir), 0.0, 1.0);
+ float m2 = m * m;
+ m = m2 * m2 * m; // pow(m,5)
+ float fresnel_term = f0 + (1.0 - f0) * m; // Fresnel Schlick term.
+
+ // The alpha value of final_color controls the blending with specular light in specular_merge.glsl.
+ // Note that the Fresnel term is multiplied with the RGB color instead of being a part of the alpha value.
+ // There is a key difference:
+ // - multiplying a term with RGB darkens the SSR light without introducing/taking away specular light.
+ // - combining a term into the Alpha value introduces specular light at the expense of the SSR light.
+ vec4 final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb * fresnel_term, fade * margin_blend * roughness_fade);
+
+ imageStore(ssr_image, ssC, final_color);
#ifdef MODE_ROUGH
@@ -259,20 +284,6 @@ void main() {
#endif // MODE_ROUGH
- final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend * roughness_fade);
-
- // Schlick term.
- float metallic = texelFetch(source_metallic, ssC << 1, 0).w;
- // F0 is the reflectance of normally incident light (perpendicular to the surface).
- // Dielectric materials have a widely accepted default value of 0.04. We assume that metals reflect all light, so their F0 is 1.0.
- float f0 = mix(0.04, 1.0, metallic);
- float m = clamp(1.0 - dot(normal, -view_dir), 0.0, 1.0);
- float m2 = m * m;
- m = m2 * m2 * m; // pow(m,5)
- final_color.a *= f0 + (1.0 - f0) * m; // Fresnel Schlick term.
-
- imageStore(ssr_image, ssC, final_color);
-
} else {
#ifdef MODE_ROUGH
imageStore(blur_radius_image, ssC, vec4(0.0));
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 8e6db7583e..206c2fb245 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -1019,13 +1019,11 @@ void fragment_shader(in SceneData scene_data) {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef MODE_RENDER_DEPTH
-#ifdef USE_OPAQUE_PREPASS
-#ifndef ALPHA_SCISSOR_USED
+#if defined(USE_OPAQUE_PREPASS) || defined(ALPHA_ANTIALIASING_EDGE_USED)
if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
-#endif // !ALPHA_SCISSOR_USED
-#endif // USE_OPAQUE_PREPASS
+#endif // USE_OPAQUE_PREPASS || ALPHA_ANTIALIASING_EDGE_USED
#endif // MODE_RENDER_DEPTH
#endif // !USE_SHADOW_TO_OPACITY
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index a9e9a617d6..5ed3669703 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -854,13 +854,11 @@ void main() {
#endif // ALPHA_ANTIALIASING_EDGE_USED
#ifdef MODE_RENDER_DEPTH
-#ifdef USE_OPAQUE_PREPASS
-#ifndef ALPHA_SCISSOR_USED
+#if defined(USE_OPAQUE_PREPASS) || defined(ALPHA_ANTIALIASING_EDGE_USED)
if (alpha < scene_data.opaque_prepass_threshold) {
discard;
}
-#endif // !ALPHA_SCISSOR_USED
-#endif // USE_OPAQUE_PREPASS
+#endif // USE_OPAQUE_PREPASS || ALPHA_ANTIALIASING_EDGE_USED
#endif // MODE_RENDER_DEPTH
#endif // !USE_SHADOW_TO_OPACITY
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index 7ba03a27f7..5fa4154727 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -67,7 +67,7 @@ struct FrameParams {
float delta;
uint frame;
- uint pad0;
+ float amount_ratio;
uint pad1;
uint pad2;
@@ -77,6 +77,8 @@ struct FrameParams {
float particle_size;
mat4 emission_transform;
+ vec3 emitter_velocity;
+ float interp_to_end;
Attractor attractors[MAX_ATTRACTORS];
Collider colliders[MAX_COLLIDERS];
diff --git a/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h
index bedf5e80c7..c8f8d4f7f2 100644
--- a/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h
@@ -59,7 +59,7 @@ public:
virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) { return -1; }
virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) {}
- virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) {}
+ virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index, uint64_t p_last_pass) {}
virtual bool uses_forward_ids() const { return false; }
};
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 4fd33ad71a..1f6d1021f4 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -793,7 +793,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
real_t distance = (i < omni_light_count) ? omni_light_sort[index].depth : spot_light_sort[index].depth;
if (using_forward_ids) {
- forward_id_storage->map_forward_id(type == RS::LIGHT_OMNI ? RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT : RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id, index);
+ forward_id_storage->map_forward_id(type == RS::LIGHT_OMNI ? RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT : RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id, index, light_instance->last_pass);
}
Transform3D light_transform = light_instance->transform;
@@ -1670,7 +1670,7 @@ void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, c
ReflectionProbeInstance *rpi = reflection_sort[i].probe_instance;
if (using_forward_ids) {
- forward_id_storage->map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i);
+ forward_id_storage->map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i, rpi->last_pass);
}
ReflectionProbe *probe = reflection_probe_owner.get_or_null(rpi->probe);
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 3bd35c53cc..2e8c9d7f8e 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -2115,7 +2115,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
return;
}
- ERR_FAIL_COND(shader->data == nullptr);
+ ERR_FAIL_NULL(shader->data);
material->data = material_data_request_func[shader->type](shader->data);
material->data->self = p_material;
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 14605b308e..da55b68109 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -356,14 +356,12 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
#else
if (surface_version != uint64_t(RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION)) {
- RS::_fix_surface_compatibility(new_surface);
+ RS::get_singleton()->fix_surface_compatibility(new_surface);
surface_version = new_surface.format & (RS::ARRAY_FLAG_FORMAT_VERSION_MASK << RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT);
ERR_FAIL_COND_MSG(surface_version != RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION,
- "Surface version provided (" +
- itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
- ") does not match current version (" +
- itos((RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) +
- ")");
+ vformat("Surface version provided (%d) does not match current version (%d).",
+ (surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK,
+ (RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK));
}
#endif
@@ -593,7 +591,6 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
// When using an uncompressed buffer with normals, but without tangents, we have to trim the padding.
if (!(s.format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && (s.format & RS::ARRAY_FORMAT_NORMAL) && !(s.format & RS::ARRAY_FORMAT_TANGENT)) {
- Vector<uint8_t> new_vertex_data;
sd.vertex_data.resize(sd.vertex_data.size() - sizeof(uint16_t) * 2);
}
}
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index f03334baac..db54816e09 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -469,7 +469,7 @@ public:
}
}
- _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ _FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
s->version_lock.lock();
@@ -501,7 +501,7 @@ public:
s->version_lock.unlock();
}
- _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint32_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
+ _FORCE_INLINE_ void mesh_instance_surface_get_vertex_arrays_and_format(RID p_mesh_instance, uint64_t p_surface_index, uint64_t p_input_mask, bool p_input_motion_vectors, RID &r_vertex_array_rd, RD::VertexFormatID &r_vertex_format) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
ERR_FAIL_NULL(mi);
Mesh *mesh = mi->mesh;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index bf5a597bb9..3d3cb585ac 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -72,6 +72,7 @@ ParticlesStorage::ParticlesStorage() {
actions.renames["ACTIVE"] = "particle_active";
actions.renames["RESTART"] = "restart";
actions.renames["CUSTOM"] = "PARTICLE.custom";
+ actions.renames["AMOUNT_RATIO"] = "FRAME.amount_ratio";
for (int i = 0; i < ParticlesShader::MAX_USERDATAS; i++) {
String udname = "USERDATA" + itos(i + 1);
actions.renames[udname] = "PARTICLE.userdata" + itos(i + 1);
@@ -88,6 +89,8 @@ ParticlesStorage::ParticlesStorage() {
actions.renames["INDEX"] = "index";
//actions.renames["GRAVITY"] = "current_gravity";
actions.renames["EMISSION_TRANSFORM"] = "FRAME.emission_transform";
+ actions.renames["EMITTER_VELOCITY"] = "FRAME.emitter_velocity";
+ actions.renames["INTERPOLATE_TO_END"] = "FRAME.interp_to_end";
actions.renames["RANDOM_SEED"] = "FRAME.random_seed";
actions.renames["FLAG_EMIT_POSITION"] = "EMISSION_FLAG_HAS_POSITION";
actions.renames["FLAG_EMIT_ROT_SCALE"] = "EMISSION_FLAG_HAS_ROTATION_SCALE";
@@ -221,13 +224,15 @@ RID ParticlesStorage::particles_allocate() {
}
void ParticlesStorage::particles_initialize(RID p_rid) {
- particles_owner.initialize_rid(p_rid, Particles());
+ particles_owner.initialize_rid(p_rid);
}
void ParticlesStorage::particles_free(RID p_rid) {
- update_particles();
Particles *particles = particles_owner.get_or_null(p_rid);
+
particles->dependency.deleted_notify(p_rid);
+ particles->update_list.remove_from_list();
+
_particles_free_data(particles);
particles_owner.free(p_rid);
}
@@ -329,6 +334,13 @@ void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
+void ParticlesStorage::particles_set_amount_ratio(RID p_particles, float p_amount_ratio) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_NULL(particles);
+
+ particles->amount_ratio = p_amount_ratio;
+}
+
void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
@@ -577,8 +589,10 @@ void ParticlesStorage::particles_request_process(RID p_particles) {
if (!particles->dirty) {
particles->dirty = true;
- particles->update_list = particle_update_list;
- particle_update_list = particles;
+
+ if (!particles->update_list.in_list()) {
+ particle_update_list.add(&particles->update_list);
+ }
}
}
@@ -651,6 +665,20 @@ void ParticlesStorage::particles_set_emission_transform(RID p_particles, const T
particles->emission_transform = p_transform;
}
+void ParticlesStorage::particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_NULL(particles);
+
+ particles->emitter_velocity = p_velocity;
+}
+
+void ParticlesStorage::particles_set_interp_to_end(RID p_particles, float p_interp) {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_NULL(particles);
+
+ particles->interp_to_end = p_interp;
+}
+
int ParticlesStorage::particles_get_draw_passes(RID p_particles) const {
const Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, 0);
@@ -791,9 +819,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
frame_params.cycle = p_particles->cycle_number;
frame_params.frame = p_particles->frame_counter++;
- frame_params.pad0 = 0;
+ frame_params.amount_ratio = p_particles->amount_ratio;
frame_params.pad1 = 0;
frame_params.pad2 = 0;
+ frame_params.emitter_velocity[0] = p_particles->emitter_velocity.x;
+ frame_params.emitter_velocity[1] = p_particles->emitter_velocity.y;
+ frame_params.emitter_velocity[2] = p_particles->emitter_velocity.z;
+ frame_params.interp_to_end = p_particles->interp_to_end;
{ //collision and attractors
@@ -1345,14 +1377,12 @@ void ParticlesStorage::_particles_update_buffers(Particles *particles) {
void ParticlesStorage::update_particles() {
uint32_t frame = RSG::rasterizer->get_frame_number();
bool uses_motion_vectors = RSG::viewport->get_num_viewports_with_motion_vectors() > 0;
- while (particle_update_list) {
+ while (particle_update_list.first()) {
//use transform feedback to process particles
- Particles *particles = particle_update_list;
+ Particles *particles = particle_update_list.first()->self();
- //take and remove
- particle_update_list = particles->update_list;
- particles->update_list = nullptr;
+ particles->update_list.remove_from_list();
particles->dirty = false;
_particles_update_buffers(particles);
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index b93932f482..a28d7b4154 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -123,7 +123,7 @@ private:
float delta;
uint32_t frame;
- uint32_t pad0;
+ float amount_ratio;
uint32_t pad1;
uint32_t pad2;
@@ -134,6 +134,9 @@ private:
float emission_transform[16];
+ float emitter_velocity[3];
+ float interp_to_end;
+
Attractor attractors[MAX_ATTRACTORS];
Collider colliders[MAX_COLLIDERS];
};
@@ -206,7 +209,7 @@ private:
RID particles_sort_uniform_set;
bool dirty = false;
- Particles *update_list = nullptr;
+ SelfList<Particles> update_list;
RID sub_emitter;
@@ -235,6 +238,9 @@ private:
bool force_sub_emit = false;
Transform3D emission_transform;
+ Vector3 emitter_velocity;
+ float interp_to_end = 0.0;
+ float amount_ratio = 1.0;
Vector<uint8_t> emission_buffer_data;
@@ -250,7 +256,8 @@ private:
LocalVector<ParticlesFrameParams> frame_history;
LocalVector<ParticlesFrameParams> trail_params;
- Particles() {
+ Particles() :
+ update_list(this) {
}
};
@@ -322,7 +329,7 @@ private:
} particles_shader;
- Particles *particle_update_list = nullptr;
+ SelfList<Particles>::List particle_update_list;
mutable RID_Owner<Particles, true> particles_owner;
@@ -425,6 +432,7 @@ public:
virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) override;
virtual void particles_set_emitting(RID p_particles, bool p_emitting) override;
virtual void particles_set_amount(RID p_particles, int p_amount) override;
+ virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) override;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
@@ -460,6 +468,8 @@ public:
virtual AABB particles_get_aabb(RID p_particles) const override;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) override;
+ virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) override;
+ virtual void particles_set_interp_to_end(RID p_particles, float p_interp_to_end) override;
virtual bool particles_get_emitting(RID p_particles) override;
virtual int particles_get_draw_passes(RID p_particles) const override;
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
index 43704119e7..b2946e6bbc 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
@@ -58,6 +58,7 @@
#define RB_TEX_BLUR_1 SNAME("blur_1")
#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster!
+#define RB_TEX_BACK_COLOR SNAME("back_color")
#define RB_TEX_BACK_DEPTH SNAME("back_depth")
class RenderSceneBuffersRD : public RenderSceneBuffers {
@@ -267,7 +268,16 @@ public:
}
// back buffer (color)
- RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here.
+ RID get_back_buffer_texture() const {
+ // Prefer returning the dedicated backbuffer color texture if it was created. Return the reused blur texture otherwise.
+ if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR)) {
+ return get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR);
+ } else if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) {
+ return get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0);
+ } else {
+ return RID();
+ }
+ }
// Upscaled.
void ensure_upscaled();
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 166b850864..678564a0e4 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -2862,7 +2862,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
Decal *decal = decal_sort[i].decal;
if (using_forward_ids) {
- forward_id_storage->map_forward_id(FORWARD_ID_TYPE_DECAL, decal_instance->forward_id, i);
+ forward_id_storage->map_forward_id(FORWARD_ID_TYPE_DECAL, decal_instance->forward_id, i, RSG::rasterizer->get_frame_number());
}
decal_instance->cull_mask = decal->cull_mask;
@@ -3511,7 +3511,9 @@ Rect2i TextureStorage::_render_target_get_sdf_rect(const RenderTarget *rt) const
scale = 200;
} break;
default: {
- }
+ ERR_PRINT("Invalid viewport SDF oversize, defaulting to 100%.");
+ scale = 100;
+ } break;
}
margin = (rt->size * scale / 100) - rt->size;
@@ -3603,6 +3605,7 @@ void TextureStorage::_render_target_allocate_sdf(RenderTarget *rt) {
scale = 25;
} break;
default: {
+ ERR_PRINT("Invalid viewport SDF scale, defaulting to 100%.");
scale = 100;
} break;
}
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 1c5cbe9612..73aacf311f 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -2239,7 +2239,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
// This trick here is what stabilizes the shadow (make potential jaggies to not move)
// at the cost of some wasted resolution. Still, the quality increase is very well worth it.
- const real_t unit = (radius + soft_shadow_expand) * 2.0 / texture_size;
+ const real_t unit = (radius + soft_shadow_expand) * 4.0 / texture_size;
x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit);
x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit);
y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit);
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 34d6a93e36..6b47c29382 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -116,19 +116,30 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
p_viewport->render_buffers.unref();
} else {
+ const float EPSILON = 0.0001;
float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
+ bool upscaler_available = p_viewport->fsr_enabled;
+
+ if ((!upscaler_available || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_BILINEAR || scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && scaling_3d_scale >= (1.0 - EPSILON) && scaling_3d_scale <= (1.0 + EPSILON)) {
+ // No 3D scaling on bilinear or FSR? Ignore scaling mode, this just introduces overhead.
+ // - Mobile can't perform optimal path
+ // - FSR does an extra pass (or 2 extra passes if 2D-MSAA is enabled)
+ // Scaling = 1.0 on FSR2 has benefits
+ scaling_3d_scale = 1.0;
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
+ }
+
bool scaling_3d_is_fsr = (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) || (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2);
bool use_taa = p_viewport->use_taa;
- if (scaling_3d_is_fsr && (scaling_3d_scale > 1.0)) {
+ if (scaling_3d_is_fsr && (scaling_3d_scale >= (1.0 + EPSILON))) {
// FSR is not designed for downsampling.
// Fall back to bilinear scaling.
WARN_PRINT_ONCE("FSR 3D resolution scaling is not designed for downsampling. Falling back to bilinear 3D resolution scaling.");
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_BILINEAR;
}
- bool upscaler_available = p_viewport->fsr_enabled;
if (scaling_3d_is_fsr && !upscaler_available) {
// FSR is not actually available.
// Fall back to bilinear scaling.
@@ -143,8 +154,8 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
use_taa = false;
}
- int width;
- int height;
+ int target_width;
+ int target_height;
int render_width;
int render_height;
@@ -152,40 +163,40 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
case RS::VIEWPORT_SCALING_3D_MODE_BILINEAR:
// Clamp 3D rendering resolution to reasonable values supported on most hardware.
// This prevents freezing the engine or outright crashing on lower-end GPUs.
- width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
- height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);
- render_width = width;
- render_height = height;
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = CLAMP(target_width * scaling_3d_scale, 1, 16384);
+ render_height = CLAMP(target_height * scaling_3d_scale, 1, 16384);
break;
case RS::VIEWPORT_SCALING_3D_MODE_FSR:
case RS::VIEWPORT_SCALING_3D_MODE_FSR2:
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = MAX(width * scaling_3d_scale, 1.0); // width / (width * scaling)
- render_height = MAX(height * scaling_3d_scale, 1.0);
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = MAX(target_width * scaling_3d_scale, 1.0); // target_width / (target_width * scaling)
+ render_height = MAX(target_height * scaling_3d_scale, 1.0);
break;
case RS::VIEWPORT_SCALING_3D_MODE_OFF:
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = width;
- render_height = height;
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = target_width;
+ render_height = target_height;
break;
default:
// This is an unknown mode.
WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
scaling_3d_scale = 1.0;
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = width;
- render_height = height;
+ target_width = p_viewport->size.width;
+ target_height = p_viewport->size.height;
+ render_width = target_width;
+ render_height = target_height;
break;
}
uint32_t jitter_phase_count = 0;
if (scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2) {
// Implementation has been copied from ffxFsr2GetJitterPhaseCount.
- jitter_phase_count = uint32_t(8.0f * pow(float(width) / render_width, 2.0f));
+ jitter_phase_count = uint32_t(8.0f * pow(float(target_width) / render_width, 2.0f));
} else if (use_taa) {
// Default jitter count for TAA.
jitter_phase_count = 16;
@@ -201,7 +212,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
RenderSceneBuffersConfiguration rb_config;
rb_config.set_render_target(p_viewport->render_target);
rb_config.set_internal_size(Size2i(render_width, render_height));
- rb_config.set_target_size(Size2(width, height));
+ rb_config.set_target_size(Size2(target_width, target_height));
rb_config.set_view_count(p_viewport->view_count);
rb_config.set_scaling_3d_mode(scaling_3d_mode);
rb_config.set_msaa_3d(p_viewport->msaa_3d);
@@ -259,6 +270,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
/* Camera should always be BEFORE any other 3D */
+ bool can_draw_2d = !p_viewport->disable_2d && p_viewport->view_count == 1; // Stereo rendering does not support 2D, no depth data
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
int scenario_canvas_max_layer = 0;
bool force_clear_render_target = false;
@@ -272,7 +284,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (RSG::scene->is_scenario(p_viewport->scenario)) {
RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
if (RSG::scene->is_environment(environment)) {
- if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport)) {
+ if (can_draw_2d && !viewport_is_environment_disabled(p_viewport)) {
scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS;
scenario_canvas_max_layer = RSG::scene->environment_get_canvas_max_layer(environment);
} else if (RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS) {
@@ -307,7 +319,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_draw_3d(p_viewport);
}
- if (!p_viewport->disable_2d) {
+ if (can_draw_2d) {
RBMap<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 9ad2175332..cd5904f175 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -476,6 +476,8 @@ public:
FUNC2(voxel_gi_set_interior, RID, bool)
FUNC2(voxel_gi_set_use_two_bounces, RID, bool)
+ FUNC0(sdfgi_reset)
+
/* PARTICLES */
#undef ServerName
@@ -490,6 +492,7 @@ public:
FUNC2(particles_set_emitting, RID, bool)
FUNC1R(bool, particles_get_emitting, RID)
FUNC2(particles_set_amount, RID, int)
+ FUNC2(particles_set_amount_ratio, RID, float)
FUNC2(particles_set_lifetime, RID, double)
FUNC2(particles_set_one_shot, RID, bool)
FUNC2(particles_set_pre_process_time, RID, double)
@@ -521,6 +524,8 @@ public:
FUNC1R(AABB, particles_get_current_aabb, RID)
FUNC2(particles_set_emission_transform, RID, const Transform3D &)
+ FUNC2(particles_set_emitter_velocity, RID, const Vector3 &)
+ FUNC2(particles_set_interp_to_end, RID, float)
/* PARTICLES COLLISION */
@@ -891,6 +896,9 @@ public:
FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool)
+ FUNC1(canvas_item_set_debug_redraw, bool)
+ FUNC0RC(bool, canvas_item_get_debug_redraw)
+
FUNCRIDSPLIT(canvas_light)
FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 71f821205e..1e95cdde0c 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -432,13 +432,13 @@ static String _get_global_shader_uniform_from_type_and_index(const String &p_buf
return "(" + p_buffer + "[" + p_index + "].xyzw)";
}
case ShaderLanguage::TYPE_MAT2: {
- return "mat2(" + p_buffer + "[" + p_index + "].xy," + p_buffer + "[" + p_index + "+1].xy)";
+ return "mat2(" + p_buffer + "[" + p_index + "].xy," + p_buffer + "[" + p_index + "+1u].xy)";
}
case ShaderLanguage::TYPE_MAT3: {
- return "mat3(" + p_buffer + "[" + p_index + "].xyz," + p_buffer + "[" + p_index + "+1].xyz," + p_buffer + "[" + p_index + "+2].xyz)";
+ return "mat3(" + p_buffer + "[" + p_index + "].xyz," + p_buffer + "[" + p_index + "+1u].xyz," + p_buffer + "[" + p_index + "+2u].xyz)";
}
case ShaderLanguage::TYPE_MAT4: {
- return "mat4(" + p_buffer + "[" + p_index + "].xyzw," + p_buffer + "[" + p_index + "+1].xyzw," + p_buffer + "[" + p_index + "+2].xyzw," + p_buffer + "[" + p_index + "+3].xyzw)";
+ return "mat4(" + p_buffer + "[" + p_index + "].xyzw," + p_buffer + "[" + p_index + "+1u].xyzw," + p_buffer + "[" + p_index + "+2u].xyzw," + p_buffer + "[" + p_index + "+3u].xyzw)";
}
default: {
ERR_FAIL_V("void");
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 34ffc1e90f..a2da26eb65 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -1377,7 +1377,7 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea
if (p_allow_reassign) {
break;
}
- ERR_FAIL_COND_V(!p_block->parent_block, false);
+ ERR_FAIL_NULL_V(p_block->parent_block, false);
p_block = p_block->parent_block;
}
}
@@ -4639,6 +4639,10 @@ bool ShaderLanguage::_validate_assign(Node *p_node, const FunctionInfo &p_functi
return false;
}
+ if (shader->varyings.has(var->name)) {
+ return _validate_varying_assign(shader->varyings[var->name], r_message);
+ }
+
if (!(p_function_info.built_ins.has(var->name) && p_function_info.built_ins[var->name].constant)) {
return true;
}
@@ -5418,7 +5422,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
if (error) {
- _set_error(vformat(RTR("A constant value cannot be passed for '%s' parameter."), _get_qualifier_str(arg_qual)));
+ _set_error(vformat(RTR("A constant value cannot be passed for the '%s' parameter."), _get_qualifier_str(arg_qual)));
return nullptr;
}
}
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 38574b0597..a6b4646f43 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -348,6 +348,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["EMITTER_VELOCITY"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["INTERPOLATE_TO_END"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT);
@@ -359,6 +361,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_COLOR"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_CUSTOM"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["AMOUNT_RATIO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_PARTICLES].functions["start"].main_function = true;
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
@@ -379,6 +382,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["EMITTER_VELOCITY"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["INTERPOLATE_TO_END"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT);
@@ -389,6 +394,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["COLLISION_DEPTH"] = constt(ShaderLanguage::TYPE_FLOAT);
shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["ATTRACTOR_FORCE"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_PARTICLES].functions["process"].built_ins["AMOUNT_RATIO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_PARTICLES].functions["process"].main_function = true;
{
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
index 78c616f6d5..4f33de912c 100644
--- a/servers/rendering/storage/particles_storage.h
+++ b/servers/rendering/storage/particles_storage.h
@@ -49,6 +49,7 @@ public:
virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
+ virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) = 0;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
@@ -85,6 +86,8 @@ public:
virtual AABB particles_get_aabb(RID p_particles) const = 0;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0;
+ virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) = 0;
+ virtual void particles_set_interp_to_end(RID p_particles, float p_interp_to_end) = 0;
virtual int particles_get_draw_passes(RID p_particles) const = 0;
virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 94ff59f7e1..43615f0d7e 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -323,16 +323,18 @@ RID RenderingServer::get_white_texture() {
}
void _get_axis_angle(const Vector3 &p_normal, const Vector4 &p_tangent, float &r_angle, Vector3 &r_axis) {
- Vector3 tangent = Vector3(p_tangent.x, p_tangent.y, p_tangent.z);
+ Vector3 normal = p_normal.normalized();
+ Vector3 tangent = Vector3(p_tangent.x, p_tangent.y, p_tangent.z).normalized();
float d = p_tangent.w;
- Vector3 binormal = p_normal.cross(tangent);
+ Vector3 binormal = normal.cross(tangent).normalized();
+ real_t angle;
- r_angle = Math::acos((tangent.x + binormal.y + p_normal.z - 1.0) / 2.0);
- float denom = 2.0 * Math::sin(r_angle);
- r_axis.x = (p_normal.y - binormal.z) / denom;
- r_axis.y = (tangent.z - p_normal.x) / denom;
- r_axis.z = (binormal.x - tangent.y) / denom;
- r_axis.normalize();
+ Basis tbn = Basis();
+ tbn.rows[0] = tangent;
+ tbn.rows[1] = binormal;
+ tbn.rows[2] = normal;
+ tbn.get_axis_angle(r_axis, angle);
+ r_angle = float(angle);
if (d < 0.0) {
r_angle = CLAMP((1.0 - r_angle / Math_PI) * 0.5, 0.0, 0.49999);
@@ -346,13 +348,11 @@ void _get_axis_angle(const Vector3 &p_normal, const Vector4 &p_tangent, float &r
void _get_tbn_from_axis_angle(const Vector3 &p_axis, float p_angle, Vector3 &r_normal, Vector4 &r_tangent) {
float binormal_sign = p_angle > 0.5 ? 1.0 : -1.0;
float angle = Math::abs(p_angle * 2.0 - 1.0) * Math_PI;
- float c = cos(angle);
- float s = sin(angle);
- Vector3 omc_axis = (1.0 - c) * p_axis;
- Vector3 s_axis = s * p_axis;
- Vector3 tan = omc_axis.x * p_axis + Vector3(c, -s_axis.z, s_axis.y);
+
+ Basis tbn = Basis(p_axis, angle);
+ Vector3 tan = tbn.rows[0];
r_tangent = Vector4(tan.x, tan.y, tan.z, binormal_sign);
- r_normal = omc_axis.z * p_axis + Vector3(-s_axis.y, s_axis.x, c);
+ r_normal = tbn.rows[2];
}
Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint32_t *p_offsets, uint32_t p_vertex_stride, uint32_t p_normal_stride, uint32_t p_attrib_stride, uint32_t p_skin_stride, Vector<uint8_t> &r_vertex_array, Vector<uint8_t> &r_attrib_array, Vector<uint8_t> &r_skin_array, int p_vertex_array_len, Vector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb, Vector4 &r_uv_scale) {
@@ -400,7 +400,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
max_val = max_val.abs().max(min_val.abs());
max_val2 = max_val2.abs().max(min_val2.abs());
- r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0);
+ if (min_val.x >= 0.0 && min_val2.x >= 0.0 && max_val.x <= 1.0 && max_val2.x <= 1.0 &&
+ min_val.y >= 0.0 && min_val2.y >= 0.0 && max_val.y <= 1.0 && max_val2.y <= 1.0) {
+ // When all channels are in the 0-1 range, we will compress to 16-bit without scaling to
+ // preserve the bits as best as possible.
+ r_uv_scale = Vector4(0.0, 0.0, 0.0, 0.0);
+ } else {
+ r_uv_scale = Vector4(max_val.x, max_val.y, max_val2.x, max_val2.y) * Vector4(2.0, 2.0, 2.0, 2.0);
+ }
}
for (int ai = 0; ai < RS::ARRAY_MAX; ai++) {
@@ -441,25 +448,22 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
const Vector3 *src = array.ptr();
- // Setting vertices means regenerating the AABB.
- AABB aabb;
+ r_aabb = AABB();
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
// First we need to generate the AABB for the entire surface.
for (int i = 0; i < p_vertex_array_len; i++) {
if (i == 0) {
- aabb = AABB(src[i], SMALL_VEC3);
+ r_aabb = AABB(src[i], SMALL_VEC3);
} else {
- aabb.expand_to(src[i]);
+ r_aabb.expand_to(src[i]);
}
}
- bool using_normals_tangents = (p_format & RS::ARRAY_FORMAT_NORMAL) && (p_format & RS::ARRAY_FORMAT_TANGENT);
-
- if (!using_normals_tangents) {
+ if (!(p_format & RS::ARRAY_FORMAT_NORMAL)) {
// Early out if we are only setting vertex positions.
for (int i = 0; i < p_vertex_array_len; i++) {
- Vector3 pos = (src[i] - aabb.position) / aabb.size;
+ Vector3 pos = (src[i] - r_aabb.position) / r_aabb.size;
uint16_t vector[4] = {
(uint16_t)CLAMP(pos.x * 65535, 0, 65535),
(uint16_t)CLAMP(pos.y * 65535, 0, 65535),
@@ -474,13 +478,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
// Validate normal and tangent arrays.
ERR_FAIL_COND_V(p_arrays[RS::ARRAY_NORMAL].get_type() != Variant::PACKED_VECTOR3_ARRAY, ERR_INVALID_PARAMETER);
- Variant::Type tangent_type = p_arrays[RS::ARRAY_TANGENT].get_type();
- ERR_FAIL_COND_V(tangent_type != Variant::PACKED_FLOAT32_ARRAY && tangent_type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
Vector<Vector3> normal_array = p_arrays[RS::ARRAY_NORMAL];
ERR_FAIL_COND_V(normal_array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER);
const Vector3 *normal_src = normal_array.ptr();
+ Variant::Type tangent_type = p_arrays[RS::ARRAY_TANGENT].get_type();
+ ERR_FAIL_COND_V(tangent_type != Variant::PACKED_FLOAT32_ARRAY && tangent_type != Variant::PACKED_FLOAT64_ARRAY && tangent_type != Variant::NIL, ERR_INVALID_PARAMETER);
+
// We need a different version if using double precision tangents.
if (tangent_type == Variant::PACKED_FLOAT32_ARRAY) {
Vector<float> tangent_array = p_arrays[RS::ARRAY_TANGENT];
@@ -507,7 +512,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
// Store vertex position + angle.
{
- Vector3 pos = (src[i] - aabb.position) / aabb.size;
+ Vector3 pos = (src[i] - r_aabb.position) / r_aabb.size;
uint16_t vector[4] = {
(uint16_t)CLAMP(pos.x * 65535, 0, 65535),
(uint16_t)CLAMP(pos.y * 65535, 0, 65535),
@@ -518,7 +523,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(uint16_t) * 4);
}
}
- } else { // PACKED_FLOAT64_ARRAY
+ } else if (tangent_type == Variant::PACKED_FLOAT64_ARRAY) {
Vector<double> tangent_array = p_arrays[RS::ARRAY_TANGENT];
ERR_FAIL_COND_V(tangent_array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
const double *tangent_src = tangent_array.ptr();
@@ -543,7 +548,41 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
// Store vertex position + angle.
{
- Vector3 pos = (src[i] - aabb.position) / aabb.size;
+ Vector3 pos = (src[i] - r_aabb.position) / r_aabb.size;
+ uint16_t vector[4] = {
+ (uint16_t)CLAMP(pos.x * 65535, 0, 65535),
+ (uint16_t)CLAMP(pos.y * 65535, 0, 65535),
+ (uint16_t)CLAMP(pos.z * 65535, 0, 65535),
+ (uint16_t)CLAMP(angle * 65535, 0, 65535)
+ };
+
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(uint16_t) * 4);
+ }
+ }
+ } else { // No tangent array.
+ // Set data for vertex, normal, and tangent.
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ float angle;
+ Vector3 axis;
+ // Generate an arbitrary vector that is tangential to normal.
+ Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normal_src[i].normalized());
+ Vector4 tangent = Vector4(tan.x, tan.y, tan.z, 1.0);
+ _get_axis_angle(normal_src[i], tangent, angle, axis);
+
+ // Store axis.
+ {
+ Vector2 res = axis.octahedron_encode();
+ uint16_t vector[2] = {
+ (uint16_t)CLAMP(res.x * 65535, 0, 65535),
+ (uint16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
+
+ memcpy(&vw[p_offsets[RS::ARRAY_NORMAL] + i * p_normal_stride], vector, 4);
+ }
+
+ // Store vertex position + angle.
+ {
+ Vector3 pos = (src[i] - r_aabb.position) / r_aabb.size;
uint16_t vector[4] = {
(uint16_t)CLAMP(pos.x * 65535, 0, 65535),
(uint16_t)CLAMP(pos.y * 65535, 0, 65535),
@@ -562,14 +601,12 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, sizeof(float) * 3);
if (i == 0) {
- aabb = AABB(src[i], SMALL_VEC3);
+ r_aabb = AABB(src[i], SMALL_VEC3);
} else {
- aabb.expand_to(src[i]);
+ r_aabb.expand_to(src[i]);
}
}
}
-
- r_aabb = aabb;
}
} break;
@@ -598,7 +635,8 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
// If using compression we store tangent while storing vertices.
if (!(p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES)) {
Variant::Type type = p_arrays[ai].get_type();
- ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY, ERR_INVALID_PARAMETER);
+ ERR_FAIL_COND_V(type != Variant::PACKED_FLOAT32_ARRAY && type != Variant::PACKED_FLOAT64_ARRAY && type != Variant::NIL, ERR_INVALID_PARAMETER);
+
if (type == Variant::PACKED_FLOAT32_ARRAY) {
Vector<float> array = p_arrays[ai];
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
@@ -612,9 +650,15 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
(uint16_t)CLAMP(res.y * 65535, 0, 65535),
};
+ if (vector[0] == 0 && vector[1] == 65535) {
+ // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection.
+ // So we sanitize here.
+ vector[0] = 65535;
+ }
+
memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
}
- } else { // PACKED_FLOAT64_ARRAY
+ } else if (type == Variant::PACKED_FLOAT64_ARRAY) {
Vector<double> array = p_arrays[ai];
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
const double *src_ptr = array.ptr();
@@ -627,6 +671,36 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
(uint16_t)CLAMP(res.y * 65535, 0, 65535),
};
+ if (vector[0] == 0 && vector[1] == 65535) {
+ // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection.
+ // So we sanitize here.
+ vector[0] = 65535;
+ }
+
+ memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
+ }
+ } else { // No tangent array.
+ ERR_FAIL_COND_V(p_arrays[RS::ARRAY_NORMAL].get_type() != Variant::PACKED_VECTOR3_ARRAY, ERR_INVALID_PARAMETER);
+
+ Vector<Vector3> normal_array = p_arrays[RS::ARRAY_NORMAL];
+ ERR_FAIL_COND_V(normal_array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER);
+ const Vector3 *normal_src = normal_array.ptr();
+ // Set data for tangent.
+ for (int i = 0; i < p_vertex_array_len; i++) {
+ // Generate an arbitrary vector that is tangential to normal.
+ Vector3 tan = Vector3(0.0, 1.0, 0.0).cross(normal_src[i].normalized());
+ Vector2 res = tan.octahedron_tangent_encode(1.0);
+ uint16_t vector[2] = {
+ (uint16_t)CLAMP(res.x * 65535, 0, 65535),
+ (uint16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
+
+ if (vector[0] == 0 && vector[1] == 65535) {
+ // (1, 1) and (0, 1) decode to the same value, but (0, 1) messes with our compression detection.
+ // So we sanitize here.
+ vector[0] = 65535;
+ }
+
memcpy(&vw[p_offsets[ai] + i * p_normal_stride], vector, 4);
}
}
@@ -661,8 +735,11 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int i = 0; i < p_vertex_array_len; i++) {
Vector2 vec = src[i];
- // Normalize into 0-1 from possible range -uv_scale - uv_scale.
- vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5);
+ if (!r_uv_scale.is_zero_approx()) {
+ // Normalize into 0-1 from possible range -uv_scale - uv_scale.
+ vec = vec / (Vector2(r_uv_scale.x, r_uv_scale.y)) + Vector2(0.5, 0.5);
+ }
+
uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) };
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4);
}
@@ -686,8 +763,10 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
if (p_format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int i = 0; i < p_vertex_array_len; i++) {
Vector2 vec = src[i];
- // Normalize into 0-1 from possible range -uv_scale - uv_scale.
- vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5);
+ if (!r_uv_scale.is_zero_approx()) {
+ // Normalize into 0-1 from possible range -uv_scale - uv_scale.
+ vec = vec / (Vector2(r_uv_scale.z, r_uv_scale.w)) + Vector2(0.5, 0.5);
+ }
uint16_t uv[2] = { (uint16_t)CLAMP(vec.x * 65535, 0, 65535), (uint16_t)CLAMP(vec.y * 65535, 0, 65535) };
memcpy(&aw[p_offsets[ai] + i * p_attrib_stride], uv, 4);
}
@@ -907,7 +986,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint64_t p_format, uint
uint32_t RenderingServer::mesh_surface_get_format_offset(BitField<ArrayFormat> p_format, int p_vertex_len, int p_array_index) const {
ERR_FAIL_INDEX_V(p_array_index, ARRAY_MAX, 0);
- p_format = int64_t(p_format) & ~ARRAY_FORMAT_INDEX;
+ p_format = uint64_t(p_format) & ~ARRAY_FORMAT_INDEX;
uint32_t offsets[ARRAY_MAX];
uint32_t vstr;
uint32_t ntstr;
@@ -918,7 +997,7 @@ uint32_t RenderingServer::mesh_surface_get_format_offset(BitField<ArrayFormat> p
}
uint32_t RenderingServer::mesh_surface_get_format_vertex_stride(BitField<ArrayFormat> p_format, int p_vertex_len) const {
- p_format = int64_t(p_format) & ~ARRAY_FORMAT_INDEX;
+ p_format = uint64_t(p_format) & ~ARRAY_FORMAT_INDEX;
uint32_t offsets[ARRAY_MAX];
uint32_t vstr;
uint32_t ntstr;
@@ -929,18 +1008,18 @@ uint32_t RenderingServer::mesh_surface_get_format_vertex_stride(BitField<ArrayFo
}
uint32_t RenderingServer::mesh_surface_get_format_normal_tangent_stride(BitField<ArrayFormat> p_format, int p_vertex_len) const {
- p_format = int64_t(p_format) & ~ARRAY_FORMAT_INDEX;
+ p_format = uint64_t(p_format) & ~ARRAY_FORMAT_INDEX;
uint32_t offsets[ARRAY_MAX];
uint32_t vstr;
uint32_t ntstr;
uint32_t astr;
uint32_t sstr;
mesh_surface_make_offsets_from_format(p_format, p_vertex_len, 0, offsets, vstr, ntstr, astr, sstr);
- return vstr;
+ return ntstr;
}
uint32_t RenderingServer::mesh_surface_get_format_attribute_stride(BitField<ArrayFormat> p_format, int p_vertex_len) const {
- p_format = int64_t(p_format) & ~ARRAY_FORMAT_INDEX;
+ p_format = uint64_t(p_format) & ~ARRAY_FORMAT_INDEX;
uint32_t offsets[ARRAY_MAX];
uint32_t vstr;
uint32_t ntstr;
@@ -950,7 +1029,7 @@ uint32_t RenderingServer::mesh_surface_get_format_attribute_stride(BitField<Arra
return astr;
}
uint32_t RenderingServer::mesh_surface_get_format_skin_stride(BitField<ArrayFormat> p_format, int p_vertex_len) const {
- p_format = int64_t(p_format) & ~ARRAY_FORMAT_INDEX;
+ p_format = uint64_t(p_format) & ~ARRAY_FORMAT_INDEX;
uint32_t offsets[ARRAY_MAX];
uint32_t vstr;
uint32_t ntstr;
@@ -1118,6 +1197,11 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
} break;
}
ERR_FAIL_COND_V(array_len == 0, ERR_INVALID_DATA);
+ } else if (i == RS::ARRAY_NORMAL) {
+ if (p_arrays[RS::ARRAY_TANGENT].get_type() == Variant::NIL) {
+ // We must use tangents if using normals.
+ format |= (1ULL << RS::ARRAY_TANGENT);
+ }
} else if (i == RS::ARRAY_BONES) {
switch (p_arrays[i].get_type()) {
case Variant::PACKED_INT32_ARRAY: {
@@ -1182,11 +1266,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY;
}
- if (format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES && ((format & RS::ARRAY_FORMAT_NORMAL) || (format & RS::ARRAY_FORMAT_TANGENT))) {
+ if ((format & RS::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && ((format & RS::ARRAY_FORMAT_NORMAL) || (format & RS::ARRAY_FORMAT_TANGENT))) {
// If using normals or tangents, then we need all three.
ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_VERTEX), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using normals or tangents without vertex array.");
ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_NORMAL), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using tangents without normal array.");
- ERR_FAIL_COND_V_MSG(!(format & RS::ARRAY_FORMAT_TANGENT), ERR_INVALID_PARAMETER, "Can't use compression flag 'ARRAY_FLAG_COMPRESS_ATTRIBUTES' while using normals without tangent array.");
}
int vertex_array_size = (vertex_element_size + normal_element_size) * array_len;
@@ -1302,7 +1385,7 @@ void RenderingServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_p
mesh_add_surface(p_mesh, sd);
}
-Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb) const {
+Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb, const Vector4 &p_uv_scale) const {
uint32_t offsets[RS::ARRAY_MAX];
uint32_t vertex_elem_size;
@@ -1347,10 +1430,8 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
Vector3 *w = arr_3d.ptrw();
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
- bool using_normals_tangents = (p_format & RS::ARRAY_FORMAT_NORMAL) && (p_format & RS::ARRAY_FORMAT_TANGENT);
-
// We only have vertices to read, so just read them and skip everything else.
- if (!using_normals_tangents) {
+ if (!(p_format & RS::ARRAY_FORMAT_NORMAL)) {
for (int j = 0; j < p_vertex_len; j++) {
const uint16_t *v = reinterpret_cast<const uint16_t *>(&r[j * vertex_elem_size + offsets[i]]);
Vector3 vec = Vector3(float(v[0]) / 65535.0, float(v[1]) / 65535.0, float(v[2]) / 65535.0);
@@ -1387,7 +1468,7 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
tangentsw[j * 4 + 3] = tan.w;
}
ret[RS::ARRAY_NORMAL] = normals;
- ret[RS::ARRAY_FORMAT_TANGENT] = tangents;
+ ret[RS::ARRAY_TANGENT] = tangents;
} else {
for (int j = 0; j < p_vertex_len; j++) {
@@ -1460,7 +1541,12 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int j = 0; j < p_vertex_len; j++) {
const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]);
- w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ if (!p_uv_scale.is_zero_approx()) {
+ vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.x, p_uv_scale.y);
+ }
+
+ w[j] = vec;
}
} else {
for (int j = 0; j < p_vertex_len; j++) {
@@ -1480,7 +1566,11 @@ Array RenderingServer::_get_array_from_surface(uint64_t p_format, Vector<uint8_t
if (p_format & ARRAY_FLAG_COMPRESS_ATTRIBUTES) {
for (int j = 0; j < p_vertex_len; j++) {
const uint16_t *v = reinterpret_cast<const uint16_t *>(&ar[j * attrib_elem_size + offsets[i]]);
- w[j] = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ Vector2 vec = Vector2(float(v[0]) / 65535.0, float(v[1]) / 65535.0);
+ if (!p_uv_scale.is_zero_approx()) {
+ vec = (vec - Vector2(0.5, 0.5)) * Vector2(p_uv_scale.z, p_uv_scale.w);
+ }
+ w[j] = vec;
}
} else {
for (int j = 0; j < p_vertex_len; j++) {
@@ -1662,7 +1752,7 @@ TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mes
uint32_t normal_elem_size;
uint32_t attrib_elem_size;
uint32_t skin_elem_size;
- //CLAY
+
mesh_surface_make_offsets_from_format(bs_format, sd.vertex_count, 0, bs_offsets, vertex_elem_size, normal_elem_size, attrib_elem_size, skin_elem_size);
int divisor = (vertex_elem_size + normal_elem_size) * sd.vertex_count;
@@ -1677,7 +1767,7 @@ TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mes
for (uint32_t i = 0; i < blend_shape_count; i++) {
Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor);
Vector<uint8_t> unused;
- blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb));
+ blend_shape_array.set(i, _get_array_from_surface(bs_format, bs_data, unused, unused, sd.vertex_count, unused, 0, sd.aabb, sd.uv_scale));
}
return blend_shape_array;
@@ -1699,7 +1789,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p
uint64_t format = p_data.format;
- return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb);
+ return _get_array_from_surface(format, vertex_data, attrib_data, skin_data, vertex_len, index_data, index_len, p_data.aabb, p_data.uv_scale);
}
#if 0
Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const {
@@ -1833,9 +1923,7 @@ static RS::SurfaceData _dict_to_surf(const Dictionary &p_dictionary) {
RS::SurfaceData sd;
sd.primitive = RS::PrimitiveType(int(p_dictionary["primitive"]));
- if (p_dictionary.has("uv_scale")) {
- sd.format = p_dictionary["format"];
- }
+ sd.format = p_dictionary["format"];
sd.vertex_data = p_dictionary["vertex_data"];
if (p_dictionary.has("attribute_data")) {
sd.attribute_data = p_dictionary["attribute_data"];
@@ -1853,7 +1941,9 @@ static RS::SurfaceData _dict_to_surf(const Dictionary &p_dictionary) {
}
sd.aabb = p_dictionary["aabb"];
- sd.uv_scale = p_dictionary["uv_scale"];
+ if (p_dictionary.has("uv_scale")) {
+ sd.uv_scale = p_dictionary["uv_scale"];
+ }
if (p_dictionary.has("lods")) {
Array lods = p_dictionary["lods"];
@@ -2024,15 +2114,39 @@ Vector<uint8_t> _convert_surface_version_1_to_surface_version_2(uint64_t p_forma
return new_vertex_data;
}
+#ifdef TOOLS_ENABLED
+void RenderingServer::set_surface_upgrade_callback(SurfaceUpgradeCallback p_callback) {
+ surface_upgrade_callback = p_callback;
+}
+
+void RenderingServer::set_warn_on_surface_upgrade(bool p_warn) {
+ warn_on_surface_upgrade = p_warn;
+}
+#endif
+
#ifndef DISABLE_DEPRECATED
-void RenderingServer::_fix_surface_compatibility(SurfaceData &p_surface) {
+void RenderingServer::fix_surface_compatibility(SurfaceData &p_surface, const String &p_path) {
uint64_t surface_version = p_surface.format & (ARRAY_FLAG_FORMAT_VERSION_MASK << ARRAY_FLAG_FORMAT_VERSION_SHIFT);
ERR_FAIL_COND_MSG(surface_version > ARRAY_FLAG_FORMAT_CURRENT_VERSION, "Cannot convert surface with version provided (" + itos((surface_version >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) + ") to current version (" + itos((RS::ARRAY_FLAG_FORMAT_CURRENT_VERSION >> RS::ARRAY_FLAG_FORMAT_VERSION_SHIFT) & RS::ARRAY_FLAG_FORMAT_VERSION_MASK) + ")");
+#ifdef TOOLS_ENABLED
+ // Editor callback to ask user about re-saving all meshes.
+ if (surface_upgrade_callback && warn_on_surface_upgrade) {
+ surface_upgrade_callback();
+ }
+
+ if (warn_on_surface_upgrade) {
+ WARN_PRINT_ONCE_ED("At least one surface uses an old surface format and needs to be upgraded. The upgrade happens automatically at load time every time until the mesh is saved again or re-imported. Once saved (or re-imported), this mesh will be incompatible with earlier versions of Godot.");
+
+ if (!p_path.is_empty()) {
+ WARN_PRINT("A surface of " + p_path + " uses an old surface format and needs to be upgraded.");
+ }
+ }
+#endif
+
if (surface_version == ARRAY_FLAG_FORMAT_VERSION_1) {
// The only difference for now is that Version 1 uses interleaved vertex positions while version 2 does not.
// I.e. PNTPNTPNT -> PPPNTNTNT.
- WARN_PRINT_ED("Upgrading mesh from older surface format. Once saved again (or re-imported), this mesh will be incompatible with earlier versions of Godot.");
int vertex_size = 0;
int normal_size = 0;
@@ -2497,11 +2611,14 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &RenderingServer::particles_set_emitting);
ClassDB::bind_method(D_METHOD("particles_get_emitting", "particles"), &RenderingServer::particles_get_emitting);
ClassDB::bind_method(D_METHOD("particles_set_amount", "particles", "amount"), &RenderingServer::particles_set_amount);
+ ClassDB::bind_method(D_METHOD("particles_set_amount_ratio", "particles", "ratio"), &RenderingServer::particles_set_amount_ratio);
ClassDB::bind_method(D_METHOD("particles_set_lifetime", "particles", "lifetime"), &RenderingServer::particles_set_lifetime);
ClassDB::bind_method(D_METHOD("particles_set_one_shot", "particles", "one_shot"), &RenderingServer::particles_set_one_shot);
ClassDB::bind_method(D_METHOD("particles_set_pre_process_time", "particles", "time"), &RenderingServer::particles_set_pre_process_time);
ClassDB::bind_method(D_METHOD("particles_set_explosiveness_ratio", "particles", "ratio"), &RenderingServer::particles_set_explosiveness_ratio);
ClassDB::bind_method(D_METHOD("particles_set_randomness_ratio", "particles", "ratio"), &RenderingServer::particles_set_randomness_ratio);
+ ClassDB::bind_method(D_METHOD("particles_set_interp_to_end", "particles", "factor"), &RenderingServer::particles_set_interp_to_end);
+ ClassDB::bind_method(D_METHOD("particles_set_emitter_velocity", "particles", "velocity"), &RenderingServer::particles_set_emitter_velocity);
ClassDB::bind_method(D_METHOD("particles_set_custom_aabb", "particles", "aabb"), &RenderingServer::particles_set_custom_aabb);
ClassDB::bind_method(D_METHOD("particles_set_speed_scale", "particles", "scale"), &RenderingServer::particles_set_speed_scale);
ClassDB::bind_method(D_METHOD("particles_set_use_local_coordinates", "particles", "enable"), &RenderingServer::particles_set_use_local_coordinates);
@@ -3330,7 +3447,7 @@ void RenderingServer::init() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"), 2);
GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality.mobile", 0);
- GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048);
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/2d/shadow_atlas/size", PROPERTY_HINT_RANGE, "128,16384"), 2048);
// Number of commands that can be drawn per frame.
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/gl_compatibility/item_buffer_size", PROPERTY_HINT_RANGE, "128,1048576,1"), 16384);
@@ -3360,8 +3477,8 @@ void RenderingServer::init() {
GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley", false);
GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley.mobile", true);
- GLOBAL_DEF("rendering/driver/depth_prepass/enable", true);
- GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
+ GLOBAL_DEF_RST("rendering/driver/depth_prepass/enable", true);
+ GLOBAL_DEF_RST("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/textures/default_filters/anisotropic_filtering_level", PROPERTY_HINT_ENUM, String::utf8("Disabled (Fastest),2× (Faster),4× (Fast),8× (Average),16× (Slow)")), 2);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 9d186f086c..fbc67fc84d 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -52,7 +52,7 @@ class RenderingServer : public Object {
int mm_policy = 0;
bool render_loop_enabled = true;
- Array _get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb) const;
+ Array _get_array_from_surface(uint64_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len, const AABB &p_aabb, const Vector4 &p_uv_scale) const;
const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON);
const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
@@ -298,6 +298,8 @@ public:
ARRAY_FLAG_FORMAT_VERSION_MASK = 0xFF, // 8 bits version
};
+ static_assert(sizeof(ArrayFormat) == 8, "ArrayFormat should be 64 bits long.");
+
enum PrimitiveType {
PRIMITIVE_POINTS,
PRIMITIVE_LINES,
@@ -631,6 +633,8 @@ public:
virtual void voxel_gi_set_quality(VoxelGIQuality) = 0;
+ virtual void sdfgi_reset() = 0;
+
/* LIGHTMAP */
virtual RID lightmap_create() = 0;
@@ -660,6 +664,7 @@ public:
virtual void particles_set_emitting(RID p_particles, bool p_enable) = 0;
virtual bool particles_get_emitting(RID p_particles) = 0;
virtual void particles_set_amount(RID p_particles, int p_amount) = 0;
+ virtual void particles_set_amount_ratio(RID p_particles, float p_amount_ratio) = 0;
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) = 0;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) = 0;
@@ -717,6 +722,8 @@ public:
virtual AABB particles_get_current_aabb(RID p_particles) = 0;
virtual void particles_set_emission_transform(RID p_particles, const Transform3D &p_transform) = 0; // This is only used for 2D, in 3D it's automatic.
+ virtual void particles_set_emitter_velocity(RID p_particles, const Vector3 &p_velocity) = 0;
+ virtual void particles_set_interp_to_end(RID p_particles, float p_interp) = 0;
/* PARTICLES COLLISION API */
@@ -1409,6 +1416,9 @@ public:
virtual void canvas_item_set_canvas_group_mode(RID p_item, CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false) = 0;
+ virtual void canvas_item_set_debug_redraw(bool p_enabled) = 0;
+ virtual bool canvas_item_get_debug_redraw() const = 0;
+
/* CANVAS LIGHT */
virtual RID canvas_light_create() = 0;
@@ -1624,8 +1634,14 @@ public:
RenderingServer();
virtual ~RenderingServer();
+#ifdef TOOLS_ENABLED
+ typedef void (*SurfaceUpgradeCallback)();
+ void set_surface_upgrade_callback(SurfaceUpgradeCallback p_callback);
+ void set_warn_on_surface_upgrade(bool p_warn);
+#endif
+
#ifndef DISABLE_DEPRECATED
- static void _fix_surface_compatibility(SurfaceData &p_surface);
+ void fix_surface_compatibility(SurfaceData &p_surface, const String &p_path = "");
#endif
private:
@@ -1641,6 +1657,10 @@ private:
TypedArray<Dictionary> _instance_geometry_get_shader_parameter_list(RID p_instance) const;
TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size);
void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses);
+#ifdef TOOLS_ENABLED
+ SurfaceUpgradeCallback surface_upgrade_callback = nullptr;
+ bool warn_on_surface_upgrade = true;
+#endif
};
// Make variant understand the enums.
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index e584146d64..d6844bba6a 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -95,6 +95,9 @@ void TextServerExtension::_bind_methods() {
GDVIRTUAL_BIND(_font_set_fixed_size, "font_rid", "fixed_size");
GDVIRTUAL_BIND(_font_get_fixed_size, "font_rid");
+ GDVIRTUAL_BIND(_font_set_fixed_size_scale_mode, "font_rid", "fixed_size_scale_mode");
+ GDVIRTUAL_BIND(_font_get_fixed_size_scale_mode, "font_rid");
+
GDVIRTUAL_BIND(_font_set_allow_system_fallback, "font_rid", "allow_system_fallback");
GDVIRTUAL_BIND(_font_is_allow_system_fallback, "font_rid");
@@ -559,6 +562,16 @@ int64_t TextServerExtension::font_get_fixed_size(const RID &p_font_rid) const {
return ret;
}
+void TextServerExtension::font_set_fixed_size_scale_mode(const RID &p_font_rid, TextServer::FixedSizeScaleMode p_fixed_size_scale_mode) {
+ GDVIRTUAL_CALL(_font_set_fixed_size_scale_mode, p_font_rid, p_fixed_size_scale_mode);
+}
+
+TextServer::FixedSizeScaleMode TextServerExtension::font_get_fixed_size_scale_mode(const RID &p_font_rid) const {
+ FixedSizeScaleMode ret = FIXED_SIZE_SCALE_DISABLE;
+ GDVIRTUAL_CALL(_font_get_fixed_size_scale_mode, p_font_rid, ret);
+ return ret;
+}
+
void TextServerExtension::font_set_allow_system_fallback(const RID &p_font_rid, bool p_allow_system_fallback) {
GDVIRTUAL_CALL(_font_set_allow_system_fallback, p_font_rid, p_allow_system_fallback);
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index c40230e723..7605ed480d 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -153,6 +153,11 @@ public:
GDVIRTUAL2(_font_set_fixed_size, RID, int64_t);
GDVIRTUAL1RC(int64_t, _font_get_fixed_size, RID);
+ virtual void font_set_fixed_size_scale_mode(const RID &p_font_rid, FixedSizeScaleMode p_fixed_size_scale) override;
+ virtual FixedSizeScaleMode font_get_fixed_size_scale_mode(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_fixed_size_scale_mode, RID, FixedSizeScaleMode);
+ GDVIRTUAL1RC(FixedSizeScaleMode, _font_get_fixed_size_scale_mode, RID);
+
virtual void font_set_subpixel_positioning(const RID &p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(const RID &p_font_rid) const override;
GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning);
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index e4eb4c730d..302d14bd8d 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -249,6 +249,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_fixed_size", "font_rid", "fixed_size"), &TextServer::font_set_fixed_size);
ClassDB::bind_method(D_METHOD("font_get_fixed_size", "font_rid"), &TextServer::font_get_fixed_size);
+ ClassDB::bind_method(D_METHOD("font_set_fixed_size_scale_mode", "font_rid", "fixed_size_scale_mode"), &TextServer::font_set_fixed_size_scale_mode);
+ ClassDB::bind_method(D_METHOD("font_get_fixed_size_scale_mode", "font_rid"), &TextServer::font_get_fixed_size_scale_mode);
+
ClassDB::bind_method(D_METHOD("font_set_allow_system_fallback", "font_rid", "allow_system_fallback"), &TextServer::font_set_allow_system_fallback);
ClassDB::bind_method(D_METHOD("font_is_allow_system_fallback", "font_rid"), &TextServer::font_is_allow_system_fallback);
@@ -619,6 +622,11 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_GDSCRIPT);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
+
+ /* Fixed size scale mode */
+ BIND_ENUM_CONSTANT(FIXED_SIZE_SCALE_DISABLE);
+ BIND_ENUM_CONSTANT(FIXED_SIZE_SCALE_INTEGER_ONLY);
+ BIND_ENUM_CONSTANT(FIXED_SIZE_SCALE_ENABLED);
}
Vector2 TextServer::get_hex_code_box_size(int64_t p_size, int64_t p_index) const {
diff --git a/servers/text_server.h b/servers/text_server.h
index 260b44da8b..fdc0e9fc4d 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -207,6 +207,12 @@ public:
STRUCTURED_TEXT_CUSTOM
};
+ enum FixedSizeScaleMode {
+ FIXED_SIZE_SCALE_DISABLE,
+ FIXED_SIZE_SCALE_INTEGER_ONLY,
+ FIXED_SIZE_SCALE_ENABLED,
+ };
+
void _draw_hex_code_box_number(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, uint8_t p_index, const Color &p_color) const;
protected:
@@ -281,6 +287,9 @@ public:
virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) = 0;
virtual int64_t font_get_fixed_size(const RID &p_font_rid) const = 0;
+ virtual void font_set_fixed_size_scale_mode(const RID &p_font_rid, FixedSizeScaleMode p_fixed_size_scale) = 0;
+ virtual FixedSizeScaleMode font_get_fixed_size_scale_mode(const RID &p_font_rid) const = 0;
+
virtual void font_set_allow_system_fallback(const RID &p_font_rid, bool p_allow_system_fallback) = 0;
virtual bool font_is_allow_system_fallback(const RID &p_font_rid) const = 0;
@@ -620,6 +629,7 @@ VARIANT_BITFIELD_CAST(TextServer::FontStyle);
VARIANT_ENUM_CAST(TextServer::StructuredTextParser);
VARIANT_ENUM_CAST(TextServer::FontAntialiasing);
VARIANT_ENUM_CAST(TextServer::FontLCDSubpixelLayout);
+VARIANT_ENUM_CAST(TextServer::FixedSizeScaleMode);
GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(CaretInfo);
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index 7e2c512554..dae342a037 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -198,9 +198,7 @@ void XRServer::remove_interface(const Ref<XRInterface> &p_interface) {
};
ERR_FAIL_COND_MSG(idx == -1, "Interface not found.");
-
- print_verbose("XR: Removed interface" + p_interface->get_name());
-
+ print_verbose("XR: Removed interface \"" + p_interface->get_name() + "\"");
emit_signal(SNAME("interface_removed"), p_interface->get_name());
interfaces.remove_at(idx);
};