summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/audio_server.cpp50
-rw-r--r--servers/audio_server.h24
-rw-r--r--servers/display_server.cpp4
-rw-r--r--servers/display_server.h2
-rw-r--r--servers/navigation_server_2d.cpp91
-rw-r--r--servers/navigation_server_2d.h30
-rw-r--r--servers/navigation_server_3d.cpp118
-rw-r--r--servers/navigation_server_3d.h39
-rw-r--r--servers/physics_2d/godot_area_2d.cpp25
-rw-r--r--servers/physics_2d/godot_area_2d.h10
-rw-r--r--servers/physics_2d/godot_space_2d.cpp20
-rw-r--r--servers/physics_3d/gjk_epa.cpp6
-rw-r--r--servers/physics_3d/godot_area_3d.cpp25
-rw-r--r--servers/physics_3d/godot_area_3d.h10
-rw-r--r--servers/physics_3d/godot_body_pair_3d.cpp14
-rw-r--r--servers/physics_3d/godot_body_pair_3d.h8
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.cpp17
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.h4
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.cpp103
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp2
-rw-r--r--servers/physics_3d/godot_physics_server_3d.h2
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp33
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp93
-rw-r--r--servers/physics_3d/godot_space_3d.cpp22
-rw-r--r--servers/physics_server_2d.cpp20
-rw-r--r--servers/physics_server_2d.h3
-rw-r--r--servers/physics_server_3d.cpp19
-rw-r--r--servers/physics_server_3d.h3
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h1
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h1
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp296
-rw-r--r--servers/rendering/renderer_canvas_cull.h8
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp46
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h95
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp14
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp29
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp97
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp20
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp67
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp16
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h1
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp21
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h3
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp29
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp3
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil.glsl6
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl10
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl26
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl36
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl14
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl7
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl9
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl17
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp17
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp8
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp39
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h10
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp21
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp22
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h8
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp29
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h4
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp4
-rw-r--r--servers/rendering/renderer_scene_cull.cpp36
-rw-r--r--servers/rendering/renderer_scene_render.cpp2
-rw-r--r--servers/rendering/renderer_viewport.cpp85
-rw-r--r--servers/rendering/renderer_viewport.h6
-rw-r--r--servers/rendering/rendering_device_binds.cpp2
-rw-r--r--servers/rendering/rendering_server_default.h4
-rw-r--r--servers/rendering/shader_compiler.cpp84
-rw-r--r--servers/rendering/shader_compiler.h4
-rw-r--r--servers/rendering/shader_language.cpp81
-rw-r--r--servers/rendering/shader_preprocessor.cpp168
-rw-r--r--servers/rendering/shader_preprocessor.h5
-rw-r--r--servers/rendering/shader_types.cpp4
-rw-r--r--servers/rendering/storage/mesh_storage.h1
-rw-r--r--servers/rendering/storage/render_scene_buffers.cpp4
-rw-r--r--servers/rendering/storage/render_scene_buffers.h4
-rw-r--r--servers/rendering/storage/texture_storage.h1
-rw-r--r--servers/rendering_server.cpp33
-rw-r--r--servers/rendering_server.h21
-rw-r--r--servers/text/text_server_extension.cpp4
-rw-r--r--servers/text/text_server_extension.h4
-rw-r--r--servers/text_server.cpp116
-rw-r--r--servers/text_server.h7
-rw-r--r--servers/xr/xr_positional_tracker.cpp8
-rw-r--r--servers/xr_server.h2
98 files changed, 1628 insertions, 939 deletions
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 6b4435a991..8c877e4eed 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -144,7 +144,7 @@ int AudioDriver::get_total_channels_by_speaker_mode(AudioDriver::SpeakerMode p_m
ERR_FAIL_V(2);
}
-PackedStringArray AudioDriver::get_device_list() {
+PackedStringArray AudioDriver::get_output_device_list() {
PackedStringArray list;
list.push_back("Default");
@@ -152,11 +152,11 @@ PackedStringArray AudioDriver::get_device_list() {
return list;
}
-String AudioDriver::get_device() {
+String AudioDriver::get_output_device() {
return "Default";
}
-PackedStringArray AudioDriver::capture_get_device_list() {
+PackedStringArray AudioDriver::get_input_device_list() {
PackedStringArray list;
list.push_back("Default");
@@ -238,7 +238,7 @@ void AudioServer::_driver_process(int p_frames, int32_t *p_buffer) {
#endif
if (channel_count != get_channel_count()) {
- // Amount of channels changed due to a device change
+ // Amount of channels changed due to a output_device change
// reinitialize the buses channels and buffers
init_channels_and_buffers();
}
@@ -1632,28 +1632,28 @@ Ref<AudioBusLayout> AudioServer::generate_bus_layout() const {
return state;
}
-PackedStringArray AudioServer::get_device_list() {
- return AudioDriver::get_singleton()->get_device_list();
+PackedStringArray AudioServer::get_output_device_list() {
+ return AudioDriver::get_singleton()->get_output_device_list();
}
-String AudioServer::get_device() {
- return AudioDriver::get_singleton()->get_device();
+String AudioServer::get_output_device() {
+ return AudioDriver::get_singleton()->get_output_device();
}
-void AudioServer::set_device(String device) {
- AudioDriver::get_singleton()->set_device(device);
+void AudioServer::set_output_device(String output_device) {
+ AudioDriver::get_singleton()->set_output_device(output_device);
}
-PackedStringArray AudioServer::capture_get_device_list() {
- return AudioDriver::get_singleton()->capture_get_device_list();
+PackedStringArray AudioServer::get_input_device_list() {
+ return AudioDriver::get_singleton()->get_input_device_list();
}
-String AudioServer::capture_get_device() {
- return AudioDriver::get_singleton()->capture_get_device();
+String AudioServer::get_input_device() {
+ return AudioDriver::get_singleton()->get_input_device();
}
-void AudioServer::capture_set_device(const String &p_name) {
- AudioDriver::get_singleton()->capture_set_device(p_name);
+void AudioServer::set_input_device(const String &p_name) {
+ AudioDriver::get_singleton()->set_input_device(p_name);
}
void AudioServer::set_enable_tagging_used_audio_streams(bool p_enable) {
@@ -1711,17 +1711,17 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_speaker_mode"), &AudioServer::get_speaker_mode);
ClassDB::bind_method(D_METHOD("get_mix_rate"), &AudioServer::get_mix_rate);
- ClassDB::bind_method(D_METHOD("get_device_list"), &AudioServer::get_device_list);
- ClassDB::bind_method(D_METHOD("get_device"), &AudioServer::get_device);
- ClassDB::bind_method(D_METHOD("set_device", "device"), &AudioServer::set_device);
+ ClassDB::bind_method(D_METHOD("get_output_device_list"), &AudioServer::get_output_device_list);
+ ClassDB::bind_method(D_METHOD("get_output_device"), &AudioServer::get_output_device);
+ ClassDB::bind_method(D_METHOD("set_output_device", "output_device"), &AudioServer::set_output_device);
ClassDB::bind_method(D_METHOD("get_time_to_next_mix"), &AudioServer::get_time_to_next_mix);
ClassDB::bind_method(D_METHOD("get_time_since_last_mix"), &AudioServer::get_time_since_last_mix);
ClassDB::bind_method(D_METHOD("get_output_latency"), &AudioServer::get_output_latency);
- ClassDB::bind_method(D_METHOD("capture_get_device_list"), &AudioServer::capture_get_device_list);
- ClassDB::bind_method(D_METHOD("capture_get_device"), &AudioServer::capture_get_device);
- ClassDB::bind_method(D_METHOD("capture_set_device", "name"), &AudioServer::capture_set_device);
+ ClassDB::bind_method(D_METHOD("get_input_device_list"), &AudioServer::get_input_device_list);
+ ClassDB::bind_method(D_METHOD("get_input_device"), &AudioServer::get_input_device);
+ ClassDB::bind_method(D_METHOD("set_input_device", "name"), &AudioServer::set_input_device);
ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout);
ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout);
@@ -1729,11 +1729,11 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enable_tagging_used_audio_streams", "enable"), &AudioServer::set_enable_tagging_used_audio_streams);
ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "capture_device"), "capture_set_device", "capture_get_device");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "output_device"), "set_output_device", "get_output_device");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "input_device"), "set_input_device", "get_input_device");
// The default value may be set to an empty string by the platform-specific audio driver.
// Override for class reference generation purposes.
- ADD_PROPERTY_DEFAULT("capture_device", "Default");
+ ADD_PROPERTY_DEFAULT("input_device", "Default");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "playback_speed_scale"), "set_playback_speed_scale", "get_playback_speed_scale");
ADD_SIGNAL(MethodInfo("bus_layout_changed"));
diff --git a/servers/audio_server.h b/servers/audio_server.h
index a369efedf7..d3d87a8400 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -94,18 +94,18 @@ public:
virtual void start() = 0;
virtual int get_mix_rate() const = 0;
virtual SpeakerMode get_speaker_mode() const = 0;
- virtual PackedStringArray get_device_list();
- virtual String get_device();
- virtual void set_device(String device) {}
+ virtual PackedStringArray get_output_device_list();
+ virtual String get_output_device();
+ virtual void set_output_device(String output_device) {}
virtual void lock() = 0;
virtual void unlock() = 0;
virtual void finish() = 0;
virtual Error capture_start() { return FAILED; }
virtual Error capture_stop() { return FAILED; }
- virtual void capture_set_device(const String &p_name) {}
- virtual String capture_get_device() { return "Default"; }
- virtual PackedStringArray capture_get_device_list();
+ virtual void set_input_device(const String &p_name) {}
+ virtual String get_input_device() { return "Default"; }
+ virtual PackedStringArray get_input_device_list();
virtual float get_latency() { return 0; }
@@ -419,13 +419,13 @@ public:
void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout);
Ref<AudioBusLayout> generate_bus_layout() const;
- PackedStringArray get_device_list();
- String get_device();
- void set_device(String device);
+ PackedStringArray get_output_device_list();
+ String get_output_device();
+ void set_output_device(String output_device);
- PackedStringArray capture_get_device_list();
- String capture_get_device();
- void capture_set_device(const String &p_name);
+ PackedStringArray get_input_device_list();
+ String get_input_device();
+ void set_input_device(const String &p_name);
void set_enable_tagging_used_audio_streams(bool p_enable);
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 82343e0402..2d65cea432 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -344,7 +344,6 @@ DisplayServer::MouseMode DisplayServer::mouse_get_mode() const {
}
void DisplayServer::warp_mouse(const Point2i &p_position) {
- WARN_PRINT("Mouse warping is not supported by this display server.");
}
Point2i DisplayServer::mouse_get_position() const {
@@ -572,7 +571,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("global_menu_add_icon_check_item", "menu_root", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_add_radio_check_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_radio_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_add_icon_radio_check_item", "menu_root", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_radio_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("global_menu_add_multistate_item", "menu_root", "labe", "max_states", "default_state", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_multistate_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_multistate_item", "menu_root", "label", "max_states", "default_state", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_multistate_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu_root", "index"), &DisplayServer::global_menu_add_separator, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_get_item_index_from_text", "menu_root", "text"), &DisplayServer::global_menu_get_item_index_from_text);
@@ -848,6 +847,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS);
BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP);
BIND_ENUM_CONSTANT(WINDOW_FLAG_EXTEND_TO_TITLE);
+ BIND_ENUM_CONSTANT(WINDOW_FLAG_MOUSE_PASSTHROUGH);
BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX);
BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER);
diff --git a/servers/display_server.h b/servers/display_server.h
index f8ade60aca..aa30b25b65 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -311,6 +311,7 @@ public:
WINDOW_FLAG_NO_FOCUS,
WINDOW_FLAG_POPUP,
WINDOW_FLAG_EXTEND_TO_TITLE,
+ WINDOW_FLAG_MOUSE_PASSTHROUGH,
WINDOW_FLAG_MAX,
};
@@ -323,6 +324,7 @@ public:
WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS),
WINDOW_FLAG_POPUP_BIT = (1 << WINDOW_FLAG_POPUP),
WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE),
+ WINDOW_FLAG_MOUSE_PASSTHROUGH_BIT = (1 << WINDOW_FLAG_MOUSE_PASSTHROUGH),
};
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 943b2ae467..85ba8ed431 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -81,35 +81,12 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr;
return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1))); \
}
-#define FORWARD_4(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) { \
- return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \
- }
-
-#define FORWARD_4_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \
- const { \
- return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3))); \
- }
-
-#define FORWARD_4_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \
- const { \
- return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \
- }
-
#define FORWARD_5_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \
NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \
const { \
return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4))); \
}
-#define FORWARD_5_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \
- const { \
- return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4)); \
- }
-
static RID rid_to_rid(const RID d) {
return d;
}
@@ -155,18 +132,14 @@ static Transform3D trf2_to_trf3(const Transform2D &d) {
return Transform3D(b, o);
}
-static StringName sn_to_sn(const StringName &d) {
- return d;
-}
-
-static Variant var_to_var(const Variant &d) {
- return d;
-}
-
static ObjectID id_to_id(const ObjectID &id) {
return id;
}
+static Callable callable_to_callable(const Callable &c) {
+ return c;
+}
+
static Ref<NavigationMesh> poly_to_mesh(Ref<NavigationPolygon> d) {
if (d.is_valid()) {
return d->get_navigation_mesh();
@@ -234,6 +207,30 @@ void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool
bool NavigationServer2D::get_debug_navigation_enable_edge_connections() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections();
}
+
+void NavigationServer2D::set_debug_navigation_agent_path_color(const Color &p_color) {
+ NavigationServer3D::get_singleton()->set_debug_navigation_agent_path_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_agent_path_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_color();
+}
+
+void NavigationServer2D::set_debug_navigation_enable_agent_paths(const bool p_value) {
+ NavigationServer3D::get_singleton()->set_debug_navigation_enable_agent_paths(p_value);
+}
+
+bool NavigationServer2D::get_debug_navigation_enable_agent_paths() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_enable_agent_paths();
+}
+
+void NavigationServer2D::set_debug_navigation_agent_path_point_size(float p_point_size) {
+ NavigationServer3D::get_singleton()->set_debug_navigation_agent_path_point_size(p_point_size);
+}
+
+float NavigationServer2D::get_debug_navigation_agent_path_point_size() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_point_size();
+}
#endif // DEBUG_ENABLED
void NavigationServer2D::_bind_methods() {
@@ -285,10 +282,10 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer2D::link_is_bidirectional);
ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer2D::link_set_navigation_layers);
ClassDB::bind_method(D_METHOD("link_get_navigation_layers", "link"), &NavigationServer2D::link_get_navigation_layers);
- ClassDB::bind_method(D_METHOD("link_set_start_location", "link", "location"), &NavigationServer2D::link_set_start_location);
- ClassDB::bind_method(D_METHOD("link_get_start_location", "link"), &NavigationServer2D::link_get_start_location);
- ClassDB::bind_method(D_METHOD("link_set_end_location", "link", "location"), &NavigationServer2D::link_set_end_location);
- ClassDB::bind_method(D_METHOD("link_get_end_location", "link"), &NavigationServer2D::link_get_end_location);
+ ClassDB::bind_method(D_METHOD("link_set_start_position", "link", "position"), &NavigationServer2D::link_set_start_position);
+ ClassDB::bind_method(D_METHOD("link_get_start_position", "link"), &NavigationServer2D::link_get_start_position);
+ ClassDB::bind_method(D_METHOD("link_set_end_position", "link", "position"), &NavigationServer2D::link_set_end_position);
+ ClassDB::bind_method(D_METHOD("link_get_end_position", "link"), &NavigationServer2D::link_get_end_position);
ClassDB::bind_method(D_METHOD("link_set_enter_cost", "link", "enter_cost"), &NavigationServer2D::link_set_enter_cost);
ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer2D::link_get_enter_cost);
ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer2D::link_set_travel_cost);
@@ -308,19 +305,31 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer2D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer2D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer2D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "callback"), &NavigationServer2D::agent_set_callback);
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
+
+ ADD_SIGNAL(MethodInfo("navigation_debug_changed"));
}
NavigationServer2D::NavigationServer2D() {
singleton = this;
ERR_FAIL_COND_MSG(!NavigationServer3D::get_singleton(), "The Navigation3D singleton should be initialized before the 2D one.");
NavigationServer3D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationServer2D::_emit_map_changed));
+
+#ifdef DEBUG_ENABLED
+ NavigationServer3D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationServer2D::_emit_navigation_debug_changed_signal));
+#endif // DEBUG_ENABLED
}
+#ifdef DEBUG_ENABLED
+void NavigationServer2D::_emit_navigation_debug_changed_signal() {
+ emit_signal(SNAME("navigation_debug_changed"));
+}
+#endif // DEBUG_ENABLED
+
NavigationServer2D::~NavigationServer2D() {
singleton = nullptr;
}
@@ -392,10 +401,10 @@ void FORWARD_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional, rid_t
bool FORWARD_1_C(link_is_bidirectional, RID, p_link, rid_to_rid);
void FORWARD_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
uint32_t FORWARD_1_C(link_get_navigation_layers, RID, p_link, rid_to_rid);
-void FORWARD_2(link_set_start_location, RID, p_link, Vector2, p_location, rid_to_rid, v2_to_v3);
-Vector2 FORWARD_1_R_C(v3_to_v2, link_get_start_location, RID, p_link, rid_to_rid);
-void FORWARD_2(link_set_end_location, RID, p_link, Vector2, p_location, rid_to_rid, v2_to_v3);
-Vector2 FORWARD_1_R_C(v3_to_v2, link_get_end_location, RID, p_link, rid_to_rid);
+void FORWARD_2(link_set_start_position, RID, p_link, Vector2, p_position, rid_to_rid, v2_to_v3);
+Vector2 FORWARD_1_R_C(v3_to_v2, link_get_start_position, RID, p_link, rid_to_rid);
+void FORWARD_2(link_set_end_position, RID, p_link, Vector2, p_position, rid_to_rid, v2_to_v3);
+Vector2 FORWARD_1_R_C(v3_to_v2, link_get_end_position, RID, p_link, rid_to_rid);
void FORWARD_2(link_set_enter_cost, RID, p_link, real_t, p_enter_cost, rid_to_rid, real_to_real);
real_t FORWARD_1_C(link_get_enter_cost, RID, p_link, rid_to_rid);
void FORWARD_2(link_set_travel_cost, RID, p_link, real_t, p_travel_cost, rid_to_rid, real_to_real);
@@ -420,7 +429,7 @@ void FORWARD_2(agent_set_target_velocity, RID, p_agent, Vector2, p_velocity, rid
void FORWARD_2(agent_set_position, RID, p_agent, Vector2, p_position, rid_to_rid, v2_to_v3);
void FORWARD_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore, rid_to_rid, bool_to_bool);
bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
-void FORWARD_4(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, rid_to_rid, id_to_id, sn_to_sn, var_to_var);
+void FORWARD_2(agent_set_callback, RID, p_agent, Callable, p_callback, rid_to_rid, callable_to_callable);
void FORWARD_1(free, RID, p_object, rid_to_rid);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 0adf736b2a..746389404b 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -130,7 +130,7 @@ public:
virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const;
virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const;
- /// Creates a new link between locations in the nav map.
+ /// Creates a new link between positions in the nav map.
virtual RID link_create();
/// Set the map of this link.
@@ -145,13 +145,13 @@ public:
virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers);
virtual uint32_t link_get_navigation_layers(RID p_link) const;
- /// Set the start location of the link.
- virtual void link_set_start_location(RID p_link, Vector2 p_location);
- virtual Vector2 link_get_start_location(RID p_link) const;
+ /// Set the start position of the link.
+ virtual void link_set_start_position(RID p_link, Vector2 p_position);
+ virtual Vector2 link_get_start_position(RID p_link) const;
- /// Set the end location of the link.
- virtual void link_set_end_location(RID p_link, Vector2 p_location);
- virtual Vector2 link_get_end_location(RID p_link) const;
+ /// Set the end position of the link.
+ virtual void link_set_end_position(RID p_link, Vector2 p_position);
+ virtual Vector2 link_get_end_position(RID p_link) const;
/// Set the enter cost of the link.
virtual void link_set_enter_cost(RID p_link, real_t p_enter_cost);
@@ -223,7 +223,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant());
+ virtual void agent_set_callback(RID p_agent, Callable p_callback);
virtual void query_path(const Ref<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result) const;
@@ -254,6 +254,20 @@ public:
void set_debug_navigation_enable_edge_connections(const bool p_value);
bool get_debug_navigation_enable_edge_connections() const;
+
+ void set_debug_navigation_agent_path_color(const Color &p_color);
+ Color get_debug_navigation_agent_path_color() const;
+
+ void set_debug_navigation_enable_agent_paths(const bool p_value);
+ bool get_debug_navigation_enable_agent_paths() const;
+
+ void set_debug_navigation_agent_path_point_size(float p_point_size);
+ float get_debug_navigation_agent_path_point_size() const;
+#endif // DEBUG_ENABLED
+
+#ifdef DEBUG_ENABLED
+private:
+ void _emit_navigation_debug_changed_signal();
#endif // DEBUG_ENABLED
};
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 253b28a623..70897ae75c 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -30,9 +30,7 @@
#include "navigation_server_3d.h"
-#ifdef DEBUG_ENABLED
#include "core/config/project_settings.h"
-#endif // DEBUG_ENABLED
NavigationServer3D *NavigationServer3D::singleton = nullptr;
@@ -90,10 +88,10 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer3D::link_is_bidirectional);
ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer3D::link_set_navigation_layers);
ClassDB::bind_method(D_METHOD("link_get_navigation_layers", "link"), &NavigationServer3D::link_get_navigation_layers);
- ClassDB::bind_method(D_METHOD("link_set_start_location", "link", "location"), &NavigationServer3D::link_set_start_location);
- ClassDB::bind_method(D_METHOD("link_get_start_location", "link"), &NavigationServer3D::link_get_start_location);
- ClassDB::bind_method(D_METHOD("link_set_end_location", "link", "location"), &NavigationServer3D::link_set_end_location);
- ClassDB::bind_method(D_METHOD("link_get_end_location", "link"), &NavigationServer3D::link_get_end_location);
+ ClassDB::bind_method(D_METHOD("link_set_start_position", "link", "position"), &NavigationServer3D::link_set_start_position);
+ ClassDB::bind_method(D_METHOD("link_get_start_position", "link"), &NavigationServer3D::link_get_start_position);
+ ClassDB::bind_method(D_METHOD("link_set_end_position", "link", "position"), &NavigationServer3D::link_set_end_position);
+ ClassDB::bind_method(D_METHOD("link_get_end_position", "link"), &NavigationServer3D::link_get_end_position);
ClassDB::bind_method(D_METHOD("link_set_enter_cost", "link", "enter_cost"), &NavigationServer3D::link_set_enter_cost);
ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer3D::link_get_enter_cost);
ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer3D::link_set_travel_cost);
@@ -113,7 +111,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer3D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer3D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer3D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "callback"), &NavigationServer3D::agent_set_callback);
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
@@ -145,6 +143,14 @@ NavigationServer3D::NavigationServer3D() {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
+ GLOBAL_DEF("navigation/2d/default_cell_size", 1);
+ GLOBAL_DEF("navigation/2d/default_edge_connection_margin", 1);
+ GLOBAL_DEF("navigation/2d/default_link_connection_radius", 4);
+
+ GLOBAL_DEF("navigation/3d/default_cell_size", 0.25);
+ GLOBAL_DEF("navigation/3d/default_edge_connection_margin", 0.25);
+ GLOBAL_DEF("navigation/3d/default_link_connection_radius", 1.0);
+
#ifdef DEBUG_ENABLED
debug_navigation_edge_connection_color = GLOBAL_DEF("debug/shapes/navigation/edge_connection_color", Color(1.0, 0.0, 1.0, 1.0));
debug_navigation_geometry_edge_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_color", Color(0.5, 1.0, 1.0, 1.0));
@@ -153,6 +159,7 @@ NavigationServer3D::NavigationServer3D() {
debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4));
debug_navigation_link_connection_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_color", Color(1.0, 0.5, 1.0, 1.0));
debug_navigation_link_connection_disabled_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
+ debug_navigation_agent_path_color = GLOBAL_DEF("debug/shapes/navigation/agent_path_color", Color(1.0, 0.0, 0.0, 1.0));
debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections", true);
debug_navigation_enable_edge_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections_xray", true);
@@ -162,6 +169,11 @@ NavigationServer3D::NavigationServer3D() {
debug_navigation_enable_link_connections = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections", true);
debug_navigation_enable_link_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections_xray", true);
+ debug_navigation_enable_agent_paths = GLOBAL_DEF("debug/shapes/navigation/enable_agent_paths", true);
+ debug_navigation_enable_agent_paths_xray = GLOBAL_DEF("debug/shapes/navigation/enable_agent_paths_xray", true);
+
+ debug_navigation_agent_path_point_size = GLOBAL_DEF("debug/shapes/navigation/agent_path_point_size", 4.0);
+
if (Engine::get_singleton()->is_editor_hint()) {
// enable NavigationServer3D when in Editor or else navigation mesh edge connections are invisible
// on runtime tests SceneTree has "Visible Navigation" set and main iteration takes care of this
@@ -323,6 +335,42 @@ Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connection
return debug_navigation_link_connections_disabled_material;
}
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_agent_path_line_material() {
+ if (debug_navigation_agent_path_line_material.is_valid()) {
+ return debug_navigation_agent_path_line_material;
+ }
+
+ Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ material->set_albedo(debug_navigation_agent_path_color);
+ if (debug_navigation_enable_agent_paths_xray) {
+ material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+ material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
+
+ debug_navigation_agent_path_line_material = material;
+ return debug_navigation_agent_path_line_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_agent_path_point_material() {
+ if (debug_navigation_agent_path_point_material.is_valid()) {
+ return debug_navigation_agent_path_point_material;
+ }
+
+ Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ material->set_albedo(debug_navigation_agent_path_color);
+ material->set_flag(StandardMaterial3D::FLAG_USE_POINT_SIZE, true);
+ material->set_point_size(debug_navigation_agent_path_point_size);
+ if (debug_navigation_enable_agent_paths_xray) {
+ material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+ material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
+
+ debug_navigation_agent_path_point_material = material;
+ return debug_navigation_agent_path_point_material;
+}
+
void NavigationServer3D::set_debug_navigation_edge_connection_color(const Color &p_color) {
debug_navigation_edge_connection_color = p_color;
if (debug_navigation_edge_connections_material.is_valid()) {
@@ -400,6 +448,31 @@ Color NavigationServer3D::get_debug_navigation_link_connection_disabled_color()
return debug_navigation_link_connection_disabled_color;
}
+void NavigationServer3D::set_debug_navigation_agent_path_point_size(float p_point_size) {
+ debug_navigation_agent_path_point_size = MAX(0.1, p_point_size);
+ if (debug_navigation_agent_path_point_material.is_valid()) {
+ debug_navigation_agent_path_point_material->set_point_size(debug_navigation_agent_path_point_size);
+ }
+}
+
+float NavigationServer3D::get_debug_navigation_agent_path_point_size() const {
+ return debug_navigation_agent_path_point_size;
+}
+
+void NavigationServer3D::set_debug_navigation_agent_path_color(const Color &p_color) {
+ debug_navigation_agent_path_color = p_color;
+ if (debug_navigation_agent_path_line_material.is_valid()) {
+ debug_navigation_agent_path_line_material->set_albedo(debug_navigation_agent_path_color);
+ }
+ if (debug_navigation_agent_path_point_material.is_valid()) {
+ debug_navigation_agent_path_point_material->set_albedo(debug_navigation_agent_path_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_agent_path_color() const {
+ return debug_navigation_agent_path_color;
+}
+
void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) {
debug_navigation_enable_edge_connections = p_value;
debug_dirty = true;
@@ -488,6 +561,37 @@ void NavigationServer3D::set_debug_enabled(bool p_enabled) {
bool NavigationServer3D::get_debug_enabled() const {
return debug_enabled;
}
+
+void NavigationServer3D::set_debug_navigation_enable_agent_paths(const bool p_value) {
+ if (debug_navigation_enable_agent_paths != p_value) {
+ debug_dirty = true;
+ }
+
+ debug_navigation_enable_agent_paths = p_value;
+
+ if (debug_dirty) {
+ call_deferred("_emit_navigation_debug_changed_signal");
+ }
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_agent_paths() const {
+ return debug_navigation_enable_agent_paths;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_agent_paths_xray(const bool p_value) {
+ debug_navigation_enable_agent_paths_xray = p_value;
+ if (debug_navigation_agent_path_line_material.is_valid()) {
+ debug_navigation_agent_path_line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_agent_paths_xray);
+ }
+ if (debug_navigation_agent_path_point_material.is_valid()) {
+ debug_navigation_agent_path_point_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_agent_paths_xray);
+ }
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_agent_paths_xray() const {
+ return debug_navigation_enable_agent_paths_xray;
+}
+
#endif // DEBUG_ENABLED
///////////////////////////////////////////////////////
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 6c4bd2e151..bc4bdf2a30 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -145,7 +145,7 @@ public:
virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0;
virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0;
- /// Creates a new link between locations in the nav map.
+ /// Creates a new link between positions in the nav map.
virtual RID link_create() = 0;
/// Set the map of this link.
@@ -160,13 +160,13 @@ public:
virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) = 0;
virtual uint32_t link_get_navigation_layers(RID p_link) const = 0;
- /// Set the start location of the link.
- virtual void link_set_start_location(RID p_link, Vector3 p_location) = 0;
- virtual Vector3 link_get_start_location(RID p_link) const = 0;
+ /// Set the start position of the link.
+ virtual void link_set_start_position(RID p_link, Vector3 p_position) = 0;
+ virtual Vector3 link_get_start_position(RID p_link) const = 0;
- /// Set the end location of the link.
- virtual void link_set_end_location(RID p_link, Vector3 p_location) = 0;
- virtual Vector3 link_get_end_location(RID p_link) const = 0;
+ /// Set the end position of the link.
+ virtual void link_set_end_position(RID p_link, Vector3 p_position) = 0;
+ virtual Vector3 link_get_end_position(RID p_link) const = 0;
/// Set the enter cost of the link.
virtual void link_set_enter_cost(RID p_link, real_t p_enter_cost) = 0;
@@ -238,7 +238,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const = 0;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant()) = 0;
+ virtual void agent_set_callback(RID p_agent, Callable p_callback) = 0;
/// Destroy the `RID`
virtual void free(RID p_object) = 0;
@@ -287,6 +287,9 @@ private:
Color debug_navigation_geometry_face_disabled_color = Color(0.5, 0.5, 0.5, 0.4);
Color debug_navigation_link_connection_color = Color(1.0, 0.5, 1.0, 1.0);
Color debug_navigation_link_connection_disabled_color = Color(0.5, 0.5, 0.5, 1.0);
+ Color debug_navigation_agent_path_color = Color(1.0, 0.0, 0.0, 1.0);
+
+ float debug_navigation_agent_path_point_size = 4.0;
bool debug_navigation_enable_edge_connections = true;
bool debug_navigation_enable_edge_connections_xray = true;
@@ -295,6 +298,8 @@ private:
bool debug_navigation_enable_geometry_face_random_color = true;
bool debug_navigation_enable_link_connections = true;
bool debug_navigation_enable_link_connections_xray = true;
+ bool debug_navigation_enable_agent_paths = true;
+ bool debug_navigation_enable_agent_paths_xray = true;
Ref<StandardMaterial3D> debug_navigation_geometry_edge_material;
Ref<StandardMaterial3D> debug_navigation_geometry_face_material;
@@ -304,6 +309,9 @@ private:
Ref<StandardMaterial3D> debug_navigation_link_connections_material;
Ref<StandardMaterial3D> debug_navigation_link_connections_disabled_material;
+ Ref<StandardMaterial3D> debug_navigation_agent_path_line_material;
+ Ref<StandardMaterial3D> debug_navigation_agent_path_point_material;
+
public:
void set_debug_enabled(bool p_enabled);
bool get_debug_enabled() const;
@@ -329,6 +337,9 @@ public:
void set_debug_navigation_link_connection_disabled_color(const Color &p_color);
Color get_debug_navigation_link_connection_disabled_color() const;
+ void set_debug_navigation_agent_path_color(const Color &p_color);
+ Color get_debug_navigation_agent_path_color() const;
+
void set_debug_navigation_enable_edge_connections(const bool p_value);
bool get_debug_navigation_enable_edge_connections() const;
@@ -350,6 +361,15 @@ public:
void set_debug_navigation_enable_link_connections_xray(const bool p_value);
bool get_debug_navigation_enable_link_connections_xray() const;
+ void set_debug_navigation_enable_agent_paths(const bool p_value);
+ bool get_debug_navigation_enable_agent_paths() const;
+
+ void set_debug_navigation_enable_agent_paths_xray(const bool p_value);
+ bool get_debug_navigation_enable_agent_paths_xray() const;
+
+ void set_debug_navigation_agent_path_point_size(float p_point_size);
+ float get_debug_navigation_agent_path_point_size() const;
+
Ref<StandardMaterial3D> get_debug_navigation_geometry_face_material();
Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_material();
Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material();
@@ -357,6 +377,9 @@ public:
Ref<StandardMaterial3D> get_debug_navigation_edge_connections_material();
Ref<StandardMaterial3D> get_debug_navigation_link_connections_material();
Ref<StandardMaterial3D> get_debug_navigation_link_connections_disabled_material();
+
+ Ref<StandardMaterial3D> get_debug_navigation_agent_path_line_material();
+ Ref<StandardMaterial3D> get_debug_navigation_agent_path_point_material();
#endif // DEBUG_ENABLED
};
diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp
index 4d93bbfa61..4d2148aa07 100644
--- a/servers/physics_2d/godot_area_2d.cpp
+++ b/servers/physics_2d/godot_area_2d.cpp
@@ -145,11 +145,8 @@ void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Varian
case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT:
gravity_is_point = p_value;
break;
- case PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
- gravity_distance_scale = p_value;
- break;
- case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
- point_attenuation = p_value;
+ case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE:
+ gravity_point_unit_distance = p_value;
break;
case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
_set_space_override_mode(linear_damping_override_mode, (PhysicsServer2D::AreaSpaceOverrideMode)(int)p_value);
@@ -179,10 +176,8 @@ Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const {
return gravity_vector;
case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT:
return gravity_is_point;
- case PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
- return gravity_distance_scale;
- case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
- return point_attenuation;
+ case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE:
+ return gravity_point_unit_distance;
case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
return linear_damping_override_mode;
case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP:
@@ -304,13 +299,13 @@ void GodotArea2D::call_queries() {
void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const {
if (is_gravity_point()) {
- const real_t gr_distance_scale = get_gravity_distance_scale();
+ const real_t gr_unit_dist = get_gravity_point_unit_distance();
Vector2 v = get_transform().xform(get_gravity_vector()) - p_position;
- if (gr_distance_scale > 0) {
- const real_t v_length = v.length();
- if (v_length > 0) {
- const real_t v_scaled = v_length * gr_distance_scale;
- r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled)));
+ if (gr_unit_dist > 0) {
+ const real_t v_length_sq = v.length_squared();
+ if (v_length_sq > 0) {
+ const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq;
+ r_gravity = v.normalized() * gravity_strength;
} else {
r_gravity = Vector2();
}
diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h
index 07c89ecb88..234e4eb9a9 100644
--- a/servers/physics_2d/godot_area_2d.h
+++ b/servers/physics_2d/godot_area_2d.h
@@ -48,8 +48,7 @@ class GodotArea2D : public GodotCollisionObject2D {
real_t gravity = 9.80665;
Vector2 gravity_vector = Vector2(0, -1);
bool gravity_is_point = false;
- real_t gravity_distance_scale = 0.0;
- real_t point_attenuation = 1.0;
+ real_t gravity_point_unit_distance = 0.0;
real_t linear_damp = 0.1;
real_t angular_damp = 1.0;
int priority = 0;
@@ -125,11 +124,8 @@ public:
_FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; }
_FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; }
- _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale = scale; }
- _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; }
-
- _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation = p_point_attenuation; }
- _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; }
+ _FORCE_INLINE_ void set_gravity_point_unit_distance(real_t scale) { gravity_point_unit_distance = scale; }
+ _FORCE_INLINE_ real_t get_gravity_point_unit_distance() const { return gravity_point_unit_distance; }
_FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; }
_FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp
index 0a5a7c93cc..1beb5336f7 100644
--- a/servers/physics_2d/godot_space_2d.cpp
+++ b/servers/physics_2d/godot_space_2d.cpp
@@ -83,7 +83,7 @@ int GodotPhysicsDirectSpaceState2D::intersect_point(const PointParameters &p_par
continue;
}
- if (p_parameters.canvas_instance_id.is_valid() && col_obj->get_canvas_instance_id() != p_parameters.canvas_instance_id) {
+ if (col_obj->get_canvas_instance_id() != p_parameters.canvas_instance_id) {
continue;
}
@@ -1216,15 +1216,15 @@ GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() {
}
GodotSpace2D::GodotSpace2D() {
- body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
- body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0));
- body_time_to_sleep = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5);
- solver_iterations = GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/2d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16);
- contact_recycle_radius = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.0);
- contact_max_separation = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.5);
- contact_max_allowed_penetration = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 0.3);
- contact_bias = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8);
- constraint_bias = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_constraint_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.2);
+ body_linear_velocity_sleep_threshold = GLOBAL_GET("physics/2d/sleep_threshold_linear");
+ body_angular_velocity_sleep_threshold = GLOBAL_GET("physics/2d/sleep_threshold_angular");
+ body_time_to_sleep = GLOBAL_GET("physics/2d/time_before_sleep");
+ solver_iterations = GLOBAL_GET("physics/2d/solver/solver_iterations");
+ contact_recycle_radius = GLOBAL_GET("physics/2d/solver/contact_recycle_radius");
+ contact_max_separation = GLOBAL_GET("physics/2d/solver/contact_max_separation");
+ contact_max_allowed_penetration = GLOBAL_GET("physics/2d/solver/contact_max_allowed_penetration");
+ contact_bias = GLOBAL_GET("physics/2d/solver/default_contact_bias");
+ constraint_bias = GLOBAL_GET("physics/2d/solver/default_constraint_bias");
broadphase = GodotBroadPhase2D::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp
index 88f2040d17..e5678914fe 100644
--- a/servers/physics_3d/gjk_epa.cpp
+++ b/servers/physics_3d/gjk_epa.cpp
@@ -1011,9 +1011,11 @@ bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transfor
if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_margin_A, p_shape_B, p_transform_B, p_margin_B, p_transform_B.origin - p_transform_A.origin, res)) {
if (p_result_callback) {
if (p_swap) {
- p_result_callback(res.witnesses[1], 0, res.witnesses[0], 0, p_userdata);
+ Vector3 normal = (res.witnesses[1] - res.witnesses[0]).normalized();
+ p_result_callback(res.witnesses[1], 0, res.witnesses[0], 0, normal, p_userdata);
} else {
- p_result_callback(res.witnesses[0], 0, res.witnesses[1], 0, p_userdata);
+ Vector3 normal = (res.witnesses[0] - res.witnesses[1]).normalized();
+ p_result_callback(res.witnesses[0], 0, res.witnesses[1], 0, normal, p_userdata);
}
}
return true;
diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp
index cd1f3b52b9..5bf16aa688 100644
--- a/servers/physics_3d/godot_area_3d.cpp
+++ b/servers/physics_3d/godot_area_3d.cpp
@@ -152,11 +152,8 @@ void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Varian
case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT:
gravity_is_point = p_value;
break;
- case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
- gravity_distance_scale = p_value;
- break;
- case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
- point_attenuation = p_value;
+ case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE:
+ gravity_point_unit_distance = p_value;
break;
case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
_set_space_override_mode(linear_damping_override_mode, (PhysicsServer3D::AreaSpaceOverrideMode)(int)p_value);
@@ -200,10 +197,8 @@ Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const {
return gravity_vector;
case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT:
return gravity_is_point;
- case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE:
- return gravity_distance_scale;
- case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION:
- return point_attenuation;
+ case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE:
+ return gravity_point_unit_distance;
case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE:
return linear_damping_override_mode;
case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP:
@@ -333,13 +328,13 @@ void GodotArea3D::call_queries() {
void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const {
if (is_gravity_point()) {
- const real_t gr_distance_scale = get_gravity_distance_scale();
+ const real_t gr_unit_dist = get_gravity_point_unit_distance();
Vector3 v = get_transform().xform(get_gravity_vector()) - p_position;
- if (gr_distance_scale > 0) {
- const real_t v_length = v.length();
- if (v_length > 0) {
- const real_t v_scaled = v_length * gr_distance_scale;
- r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled)));
+ if (gr_unit_dist > 0) {
+ const real_t v_length_sq = v.length_squared();
+ if (v_length_sq > 0) {
+ const real_t gravity_strength = get_gravity() * gr_unit_dist * gr_unit_dist / v_length_sq;
+ r_gravity = v.normalized() * gravity_strength;
} else {
r_gravity = Vector3();
}
diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h
index 0961da5b7d..f05d0f9019 100644
--- a/servers/physics_3d/godot_area_3d.h
+++ b/servers/physics_3d/godot_area_3d.h
@@ -49,8 +49,7 @@ class GodotArea3D : public GodotCollisionObject3D {
real_t gravity = 9.80665;
Vector3 gravity_vector = Vector3(0, -1, 0);
bool gravity_is_point = false;
- real_t gravity_distance_scale = 0.0;
- real_t point_attenuation = 1.0;
+ real_t gravity_point_unit_distance = 0.0;
real_t linear_damp = 0.1;
real_t angular_damp = 0.1;
real_t wind_force_magnitude = 0.0;
@@ -134,11 +133,8 @@ public:
_FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; }
_FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; }
- _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale = scale; }
- _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; }
-
- _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation = p_point_attenuation; }
- _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; }
+ _FORCE_INLINE_ void set_gravity_point_unit_distance(real_t scale) { gravity_point_unit_distance = scale; }
+ _FORCE_INLINE_ real_t get_gravity_point_unit_distance() const { return gravity_point_unit_distance; }
_FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; }
_FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp
index ce3da390cb..619e6c00be 100644
--- a/servers/physics_3d/godot_body_pair_3d.cpp
+++ b/servers/physics_3d/godot_body_pair_3d.cpp
@@ -38,12 +38,12 @@
#define MIN_VELOCITY 0.0001
#define MAX_BIAS_ROTATION (Math_PI / 8)
-void GodotBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+void GodotBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata) {
GodotBodyPair3D *pair = static_cast<GodotBodyPair3D *>(p_userdata);
- pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
+ pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B, normal);
}
-void GodotBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
+void GodotBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal) {
Vector3 local_A = A->get_inv_transform().basis.xform(p_point_A);
Vector3 local_B = B->get_inv_transform().basis.xform(p_point_B - offset_B);
@@ -577,12 +577,12 @@ GodotBodyPair3D::~GodotBodyPair3D() {
B->remove_constraint(this);
}
-void GodotBodySoftBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+void GodotBodySoftBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata) {
GodotBodySoftBodyPair3D *pair = static_cast<GodotBodySoftBodyPair3D *>(p_userdata);
- pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B);
+ pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B, normal);
}
-void GodotBodySoftBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) {
+void GodotBodySoftBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal) {
Vector3 local_A = body->get_inv_transform().xform(p_point_A);
Vector3 local_B = p_point_B - soft_body->get_node_position(p_index_B);
@@ -591,7 +591,7 @@ void GodotBodySoftBodyPair3D::contact_added_callback(const Vector3 &p_point_A, i
contact.index_B = p_index_B;
contact.local_A = local_A;
contact.local_B = local_B;
- contact.normal = (p_point_A - p_point_B).normalized();
+ contact.normal = (normal.dot((p_point_A - p_point_B)) < 0 ? -normal : normal);
contact.used = true;
// Attempt to determine if the contact will be reused.
diff --git a/servers/physics_3d/godot_body_pair_3d.h b/servers/physics_3d/godot_body_pair_3d.h
index c3165c7fcf..a8f5180dd5 100644
--- a/servers/physics_3d/godot_body_pair_3d.h
+++ b/servers/physics_3d/godot_body_pair_3d.h
@@ -97,9 +97,9 @@ class GodotBodyPair3D : public GodotBodyContact3D {
Contact contacts[MAX_CONTACTS];
int contact_count = 0;
- static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+ static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata);
- void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B);
+ void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal);
void validate_contacts();
bool _test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B);
@@ -126,9 +126,9 @@ class GodotBodySoftBodyPair3D : public GodotBodyContact3D {
LocalVector<Contact> contacts;
- static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+ static void _contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata);
- void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B);
+ void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal);
void validate_contacts();
diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp
index 0b92b745fe..2de1d86de1 100644
--- a/servers/physics_3d/godot_collision_solver_3d.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d.cpp
@@ -81,9 +81,11 @@ bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_s
if (p_result_callback) {
if (p_swap_result) {
- p_result_callback(supports[i], 0, support_A, 0, p_userdata);
+ Vector3 normal = (support_A - supports[i]).normalized();
+ p_result_callback(supports[i], 0, support_A, 0, normal, p_userdata);
} else {
- p_result_callback(support_A, 0, supports[i], 0, p_userdata);
+ Vector3 normal = (supports[i] - support_A).normalized();
+ p_result_callback(support_A, 0, supports[i], 0, normal, p_userdata);
}
}
}
@@ -125,10 +127,11 @@ bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A,
}
if (p_result_callback) {
+ Vector3 normal = (support_B - support_A).normalized();
if (p_swap_result) {
- p_result_callback(support_B, 0, support_A, 0, p_userdata);
+ p_result_callback(support_B, 0, support_A, 0, -normal, p_userdata);
} else {
- p_result_callback(support_A, 0, support_B, 0, p_userdata);
+ p_result_callback(support_A, 0, support_B, 0, normal, p_userdata);
}
}
return true;
@@ -142,7 +145,7 @@ struct _SoftBodyContactCollisionInfo {
int contact_count = 0;
};
-void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata) {
_SoftBodyContactCollisionInfo &cinfo = *(static_cast<_SoftBodyContactCollisionInfo *>(p_userdata));
++cinfo.contact_count;
@@ -152,9 +155,9 @@ void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A
}
if (cinfo.swap_result) {
- cinfo.result_callback(p_point_B, cinfo.node_index, p_point_A, p_index_A, cinfo.userdata);
+ cinfo.result_callback(p_point_B, cinfo.node_index, p_point_A, p_index_A, -normal, cinfo.userdata);
} else {
- cinfo.result_callback(p_point_A, p_index_A, p_point_B, cinfo.node_index, cinfo.userdata);
+ cinfo.result_callback(p_point_A, p_index_A, p_point_B, cinfo.node_index, normal, cinfo.userdata);
}
}
diff --git a/servers/physics_3d/godot_collision_solver_3d.h b/servers/physics_3d/godot_collision_solver_3d.h
index 7ef0dc97ac..36ea79576e 100644
--- a/servers/physics_3d/godot_collision_solver_3d.h
+++ b/servers/physics_3d/godot_collision_solver_3d.h
@@ -35,11 +35,11 @@
class GodotCollisionSolver3D {
public:
- typedef void (*CallbackResult)(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+ typedef void (*CallbackResult)(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata);
private:
static bool soft_body_query_callback(uint32_t p_node_index, void *p_userdata);
- static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+ static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata);
static bool soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex);
static bool concave_callback(void *p_userdata, GodotShape3D *p_convex);
static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
index d13f4ee801..2cb29b3dd0 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
@@ -75,11 +75,13 @@ struct _CollectorCallback {
Vector3 normal;
Vector3 *prev_axis = nullptr;
- _FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B) {
+ _FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B, Vector3 p_normal) {
+ if (p_normal.dot(p_point_B - p_point_A) < 0)
+ p_normal = -p_normal;
if (swap) {
- callback(p_point_B, 0, p_point_A, 0, userdata);
+ callback(p_point_B, 0, p_point_A, 0, -p_normal, userdata);
} else {
- callback(p_point_A, 0, p_point_B, 0, userdata);
+ callback(p_point_A, 0, p_point_B, 0, p_normal, userdata);
}
}
};
@@ -92,7 +94,7 @@ static void _generate_contacts_point_point(const Vector3 *p_points_A, int p_poin
ERR_FAIL_COND(p_point_count_B != 1);
#endif
- p_callback->call(*p_points_A, *p_points_B);
+ p_callback->call(*p_points_A, *p_points_B, p_callback->normal);
}
static void _generate_contacts_point_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
@@ -102,7 +104,7 @@ static void _generate_contacts_point_edge(const Vector3 *p_points_A, int p_point
#endif
Vector3 closest_B = Geometry3D::get_closest_point_to_segment_uncapped(*p_points_A, p_points_B);
- p_callback->call(*p_points_A, closest_B);
+ p_callback->call(*p_points_A, closest_B, p_callback->normal);
}
static void _generate_contacts_point_face(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
@@ -111,9 +113,9 @@ static void _generate_contacts_point_face(const Vector3 *p_points_A, int p_point
ERR_FAIL_COND(p_point_count_B < 3);
#endif
- Vector3 closest_B = Plane(p_points_B[0], p_points_B[1], p_points_B[2]).project(*p_points_A);
-
- p_callback->call(*p_points_A, closest_B);
+ Plane plane(p_points_B[0], p_points_B[1], p_points_B[2]);
+ Vector3 closest_B = plane.project(*p_points_A);
+ p_callback->call(*p_points_A, closest_B, plane.get_normal());
}
static void _generate_contacts_point_circle(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
@@ -122,9 +124,9 @@ static void _generate_contacts_point_circle(const Vector3 *p_points_A, int p_poi
ERR_FAIL_COND(p_point_count_B != 3);
#endif
- Vector3 closest_B = Plane(p_points_B[0], p_points_B[1], p_points_B[2]).project(*p_points_A);
-
- p_callback->call(*p_points_A, closest_B);
+ Plane plane(p_points_B[0], p_points_B[1], p_points_B[2]);
+ Vector3 closest_B = plane.project(*p_points_A);
+ p_callback->call(*p_points_A, closest_B, plane.get_normal());
}
static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
@@ -154,8 +156,8 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_
sa.sort(dvec, 4);
//use the middle ones as contacts
- p_callback->call(base_A + axis * dvec[1], base_B + axis * dvec[1]);
- p_callback->call(base_A + axis * dvec[2], base_B + axis * dvec[2]);
+ p_callback->call(base_A + axis * dvec[1], base_B + axis * dvec[1], p_callback->normal);
+ p_callback->call(base_A + axis * dvec[2], base_B + axis * dvec[2], p_callback->normal);
return;
}
@@ -170,7 +172,14 @@ static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_
Vector3 closest_A = p_points_A[0] + rel_A * d;
Vector3 closest_B = Geometry3D::get_closest_point_to_segment_uncapped(closest_A, p_points_B);
- p_callback->call(closest_A, closest_B);
+ // The normal should be perpendicular to both edges.
+ Vector3 normal = rel_A.cross(rel_B);
+ real_t normal_len = normal.length();
+ if (normal_len > 1e-3)
+ normal /= normal_len;
+ else
+ normal = p_callback->normal;
+ p_callback->call(closest_A, closest_B, normal);
}
static void _generate_contacts_edge_circle(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) {
@@ -267,7 +276,7 @@ static void _generate_contacts_edge_circle(const Vector3 *p_points_A, int p_poin
continue;
}
- p_callback->call(contact_point_A, closest_B);
+ p_callback->call(contact_point_A, closest_B, circle_plane.get_normal());
}
}
@@ -352,7 +361,7 @@ static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_
continue;
}
- p_callback->call(clipbuf_src[i], closest_B);
+ p_callback->call(clipbuf_src[i], closest_B, plane_B.get_normal());
}
}
@@ -431,7 +440,7 @@ static void _generate_contacts_face_circle(const Vector3 *p_points_A, int p_poin
continue;
}
- p_callback->call(contact_point_A, closest_B);
+ p_callback->call(contact_point_A, closest_B, circle_plane.get_normal());
}
}
@@ -534,7 +543,7 @@ static void _generate_contacts_circle_circle(const Vector3 *p_points_A, int p_po
continue;
}
- p_callback->call(contact_point_A, closest_B);
+ p_callback->call(contact_point_A, closest_B, circle_B_plane.get_normal());
}
}
@@ -678,7 +687,7 @@ public:
return true;
}
- static _FORCE_INLINE_ void test_contact_points(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+ static _FORCE_INLINE_ void test_contact_points(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata) {
SeparatorAxisTest<ShapeA, ShapeB, withMargin> *separator = (SeparatorAxisTest<ShapeA, ShapeB, withMargin> *)p_userdata;
Vector3 axis = (p_point_B - p_point_A);
real_t depth = axis.length();
@@ -802,11 +811,11 @@ static void analytic_sphere_collision(const Vector3 &p_origin_a, real_t p_radius
if (p_radius_a < p_radius_b) {
Vector3 point_a = p_origin_a - b_to_a * p_radius_a;
Vector3 point_b = point_a + b_to_a * overlap;
- p_collector->call(point_a, point_b); // Consider adding b_to_a vector
+ p_collector->call(point_a, point_b, b_to_a); // Consider adding b_to_a vector
} else {
Vector3 point_b = p_origin_b + b_to_a * p_radius_b;
Vector3 point_a = point_b - b_to_a * overlap;
- p_collector->call(point_a, point_b); // Consider adding b_to_a vector
+ p_collector->call(point_a, point_b, b_to_a); // Consider adding b_to_a vector
}
}
@@ -818,9 +827,9 @@ static void _collision_sphere_sphere(const GodotShape3D *p_a, const Transform3D
// Perform an analytic sphere collision between the two spheres
analytic_sphere_collision<withMargin>(
p_transform_a.origin,
- sphere_A->get_radius(),
+ sphere_A->get_radius() * p_transform_a.basis[0].length(),
p_transform_b.origin,
- sphere_B->get_radius(),
+ sphere_B->get_radius() * p_transform_b.basis[0].length(),
p_collector,
p_margin_a,
p_margin_b);
@@ -833,7 +842,7 @@ static void _collision_sphere_box(const GodotShape3D *p_a, const Transform3D &p_
// Find the point on the box nearest to the center of the sphere.
- Vector3 center = p_transform_b.xform_inv(p_transform_a.origin);
+ Vector3 center = p_transform_b.affine_inverse().xform(p_transform_a.origin);
Vector3 extents = box_B->get_half_extents();
Vector3 nearest(MIN(MAX(center.x, -extents.x), extents.x),
MIN(MAX(center.y, -extents.y), extents.y),
@@ -844,7 +853,8 @@ static void _collision_sphere_box(const GodotShape3D *p_a, const Transform3D &p_
Vector3 delta = nearest - p_transform_a.origin;
real_t length = delta.length();
- if (length > sphere_A->get_radius() + p_margin_a + p_margin_b) {
+ real_t radius = sphere_A->get_radius() * p_transform_a.basis[0].length();
+ if (length > radius + p_margin_a + p_margin_b) {
return;
}
p_collector->collided = true;
@@ -858,9 +868,9 @@ static void _collision_sphere_box(const GodotShape3D *p_a, const Transform3D &p_
} else {
axis = delta / length;
}
- Vector3 point_a = p_transform_a.origin + (sphere_A->get_radius() + p_margin_a) * axis;
- Vector3 point_b = (withMargin ? nearest + p_margin_b * axis : nearest);
- p_collector->call(point_a, point_b);
+ Vector3 point_a = p_transform_a.origin + (radius + p_margin_a) * axis;
+ Vector3 point_b = (withMargin ? nearest - p_margin_b * axis : nearest);
+ p_collector->call(point_a, point_b, axis);
}
template <bool withMargin>
@@ -868,11 +878,12 @@ static void _collision_sphere_capsule(const GodotShape3D *p_a, const Transform3D
const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a);
const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b);
- real_t capsule_B_radius = capsule_B->get_radius();
+ real_t scale_A = p_transform_a.basis[0].length();
+ real_t scale_B = p_transform_b.basis[0].length();
// Construct the capsule segment (ball-center to ball-center)
Vector3 capsule_segment[2];
- Vector3 capsule_axis = p_transform_b.basis.get_column(1) * (capsule_B->get_height() * 0.5 - capsule_B_radius);
+ Vector3 capsule_axis = p_transform_b.basis.get_column(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
capsule_segment[0] = p_transform_b.origin + capsule_axis;
capsule_segment[1] = p_transform_b.origin - capsule_axis;
@@ -882,9 +893,9 @@ static void _collision_sphere_capsule(const GodotShape3D *p_a, const Transform3D
// Perform an analytic sphere collision between the sphere and the sphere-collider in the capsule
analytic_sphere_collision<withMargin>(
p_transform_a.origin,
- sphere_A->get_radius(),
+ sphere_A->get_radius() * scale_A,
capsule_closest,
- capsule_B_radius,
+ capsule_B->get_radius() * scale_B,
p_collector,
p_margin_a,
p_margin_b);
@@ -894,12 +905,12 @@ template <bool withMargin>
static void analytic_sphere_cylinder_collision(real_t p_radius_a, real_t p_radius_b, real_t p_height_b, const Transform3D &p_transform_a, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
// Find the point on the cylinder nearest to the center of the sphere.
- Vector3 center = p_transform_b.xform_inv(p_transform_a.origin);
+ Vector3 center = p_transform_b.affine_inverse().xform(p_transform_a.origin);
Vector3 nearest = center;
- real_t radius = p_radius_b;
+ real_t scale_A = p_transform_a.basis[0].length();
real_t r = Math::sqrt(center.x * center.x + center.z * center.z);
- if (r > radius) {
- real_t scale = radius / r;
+ if (r > p_radius_b) {
+ real_t scale = p_radius_b / r;
nearest.x *= scale;
nearest.z *= scale;
}
@@ -911,7 +922,7 @@ static void analytic_sphere_cylinder_collision(real_t p_radius_a, real_t p_radiu
Vector3 delta = nearest - p_transform_a.origin;
real_t length = delta.length();
- if (length > p_radius_a + p_margin_a + p_margin_b) {
+ if (length > p_radius_a * scale_A + p_margin_a + p_margin_b) {
return;
}
p_collector->collided = true;
@@ -925,9 +936,9 @@ static void analytic_sphere_cylinder_collision(real_t p_radius_a, real_t p_radiu
} else {
axis = delta / length;
}
- Vector3 point_a = p_transform_a.origin + (p_radius_a + p_margin_a) * axis;
- Vector3 point_b = (withMargin ? nearest + p_margin_b * axis : nearest);
- p_collector->call(point_a, point_b);
+ Vector3 point_a = p_transform_a.origin + (p_radius_a * scale_A + p_margin_a) * axis;
+ Vector3 point_b = (withMargin ? nearest - p_margin_b * axis : nearest);
+ p_collector->call(point_a, point_b, axis);
}
template <bool withMargin>
@@ -1623,14 +1634,14 @@ static void _collision_capsule_capsule(const GodotShape3D *p_a, const Transform3
const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a);
const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b);
- real_t capsule_A_radius = capsule_A->get_radius();
- real_t capsule_B_radius = capsule_B->get_radius();
+ real_t scale_A = p_transform_a.basis[0].length();
+ real_t scale_B = p_transform_b.basis[0].length();
// Get the closest points between the capsule segments
Vector3 capsule_A_closest;
Vector3 capsule_B_closest;
- Vector3 capsule_A_axis = p_transform_a.basis.get_column(1) * (capsule_A->get_height() * 0.5 - capsule_A_radius);
- Vector3 capsule_B_axis = p_transform_b.basis.get_column(1) * (capsule_B->get_height() * 0.5 - capsule_B_radius);
+ Vector3 capsule_A_axis = p_transform_a.basis.get_column(1) * (capsule_A->get_height() * 0.5 - capsule_A->get_radius());
+ Vector3 capsule_B_axis = p_transform_b.basis.get_column(1) * (capsule_B->get_height() * 0.5 - capsule_B->get_radius());
Geometry3D::get_closest_points_between_segments(
p_transform_a.origin + capsule_A_axis,
p_transform_a.origin - capsule_A_axis,
@@ -1642,9 +1653,9 @@ static void _collision_capsule_capsule(const GodotShape3D *p_a, const Transform3
// Perform the analytic collision between the two closest capsule spheres
analytic_sphere_collision<withMargin>(
capsule_A_closest,
- capsule_A_radius,
+ capsule_A->get_radius() * scale_A,
capsule_B_closest,
- capsule_B_radius,
+ capsule_B->get_radius() * scale_B,
p_collector,
p_margin_a,
p_margin_b);
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index e8250acb45..b6d8acfbf3 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -1737,7 +1737,7 @@ void GodotPhysicsServer3D::_update_shapes() {
}
}
-void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata) {
CollCbkData *cbk = static_cast<CollCbkData *>(p_userdata);
if (cbk->max == 0) {
diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h
index 3da0c6debe..040e673dcd 100644
--- a/servers/physics_3d/godot_physics_server_3d.h
+++ b/servers/physics_3d/godot_physics_server_3d.h
@@ -77,7 +77,7 @@ public:
Vector3 *ptr = nullptr;
};
- static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
+ static void _shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata);
virtual RID world_boundary_shape_create() override;
virtual RID separation_ray_shape_create() override;
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 8aacfa929f..300dca4e08 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -852,17 +852,12 @@ Vector3 GodotConvexPolygonShape3D::get_support(const Vector3 &p_normal) const {
// Get the array of vertices
const Vector3 *const vertices_array = mesh.vertices.ptr();
- // Get the array of extreme vertices
- const int *const extreme_array = extreme_vertices.ptr();
- const uint32_t extreme_size = extreme_vertices.size();
-
- // Start with an initial assumption of the first extreme vertex
- int best_vertex = extreme_array[0];
+ // Start with an initial assumption of the first extreme vertex.
+ int best_vertex = extreme_vertices[0];
real_t max_support = p_normal.dot(vertices_array[best_vertex]);
- // Check the remaining extreme vertices for a better vertex
- for (uint32_t i = 0; i < extreme_size; ++i) {
- int vert = extreme_array[i];
+ // Check the remaining extreme vertices for a better vertex.
+ for (const int &vert : extreme_vertices) {
real_t s = p_normal.dot(vertices_array[vert]);
if (s > max_support) {
best_vertex = vert;
@@ -870,27 +865,18 @@ Vector3 GodotConvexPolygonShape3D::get_support(const Vector3 &p_normal) const {
}
}
- // If we checked all vertices in the mesh then we're done
- if (extreme_size == mesh.vertices.size()) {
+ // If we checked all vertices in the mesh then we're done.
+ if (extreme_vertices.size() == mesh.vertices.size()) {
return vertices_array[best_vertex];
}
- // Get the array of neighbor arrays for each vertex
- const LocalVector<int> *const vertex_neighbors_array = vertex_neighbors.ptr();
-
// Move along the surface until we reach the true support vertex.
int last_vertex = -1;
while (true) {
int next_vertex = -1;
- // Get the array of neighbors around the best vertex
- const LocalVector<int> &neighbors = vertex_neighbors_array[best_vertex];
- const int *const neighbors_array = neighbors.ptr();
- const uint32_t neighbors_size = neighbors.size();
-
- // Iterate over all the neighbors checking for a better vertex
- for (uint32_t i = 0; i < neighbors_size; ++i) {
- int vert = neighbors_array[i];
+ // Iterate over all the neighbors checking for a better vertex.
+ for (const int &vert : vertex_neighbors[best_vertex]) {
if (vert != last_vertex) {
real_t s = p_normal.dot(vertices_array[vert]);
if (s > max_support) {
@@ -1149,8 +1135,7 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) {
if (extreme_vertices.size() < mesh.vertices.size()) {
vertex_neighbors.resize(mesh.vertices.size());
- for (uint32_t i = 0; i < mesh.edges.size(); i++) {
- Geometry3D::MeshData::Edge &edge = mesh.edges[i];
+ for (Geometry3D::MeshData::Edge &edge : mesh.edges) {
vertex_neighbors[edge.vertex_a].push_back(edge.vertex_b);
vertex_neighbors[edge.vertex_b].push_back(edge.vertex_a);
}
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 871017a5e7..1820a29553 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -167,14 +167,11 @@ void GodotSoftBody3D::update_rendering_server(PhysicsServer3DRenderingServerHand
}
void GodotSoftBody3D::update_normals_and_centroids() {
- uint32_t i, ni;
-
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- nodes[i].n = Vector3();
+ for (Node &node : nodes) {
+ node.n = Vector3();
}
- for (i = 0, ni = faces.size(); i < ni; ++i) {
- Face &face = faces[i];
+ for (Face &face : faces) {
const Vector3 n = vec3_cross(face.n[0]->x - face.n[2]->x, face.n[0]->x - face.n[1]->x);
face.n[0]->n += n;
face.n[1]->n += n;
@@ -184,8 +181,7 @@ void GodotSoftBody3D::update_normals_and_centroids() {
face.centroid = 0.33333333333 * (face.n[0]->x + face.n[1]->x + face.n[2]->x);
}
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- Node &node = nodes[i];
+ for (Node &node : nodes) {
real_t len = node.n.length();
if (len > CMP_EPSILON) {
node.n /= len;
@@ -235,9 +231,7 @@ void GodotSoftBody3D::update_area() {
int i, ni;
// Face area.
- for (i = 0, ni = faces.size(); i < ni; ++i) {
- Face &face = faces[i];
-
+ for (Face &face : faces) {
const Vector3 &x0 = face.n[0]->x;
const Vector3 &x1 = face.n[1]->x;
const Vector3 &x2 = face.n[2]->x;
@@ -255,12 +249,11 @@ void GodotSoftBody3D::update_area() {
memset(counts.ptr(), 0, counts.size() * sizeof(int));
}
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- nodes[i].area = 0.0;
+ for (Node &node : nodes) {
+ node.area = 0.0;
}
- for (i = 0, ni = faces.size(); i < ni; ++i) {
- const Face &face = faces[i];
+ for (const Face &face : faces) {
for (int j = 0; j < 3; ++j) {
const int index = (int)(face.n[j] - &nodes[0]);
counts[index]++;
@@ -278,8 +271,7 @@ void GodotSoftBody3D::update_area() {
}
void GodotSoftBody3D::reset_link_rest_lengths() {
- for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
- Link &link = links[i];
+ for (Link &link : links) {
link.rl = (link.n[0]->x - link.n[1]->x).length();
link.c1 = link.rl * link.rl;
}
@@ -287,8 +279,7 @@ void GodotSoftBody3D::reset_link_rest_lengths() {
void GodotSoftBody3D::update_link_constants() {
real_t inv_linear_stiffness = 1.0 / linear_stiffness;
- for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
- Link &link = links[i];
+ for (Link &link : links) {
link.c0 = (link.n[0]->im + link.n[1]->im) * inv_linear_stiffness;
}
}
@@ -619,9 +610,9 @@ void GodotSoftBody3D::generate_bending_constraints(int p_distance) {
}
}
}
- for (i = 0; i < links.size(); ++i) {
- const int ia = (int)(links[i].n[0] - &nodes[0]);
- const int ib = (int)(links[i].n[1] - &nodes[0]);
+ for (Link &link : links) {
+ const int ia = (int)(link.n[0] - &nodes[0]);
+ const int ib = (int)(link.n[1] - &nodes[0]);
int idx = ib * n + ia;
int idx_inv = ia * n + ib;
adj[idx] = 1;
@@ -635,9 +626,9 @@ void GodotSoftBody3D::generate_bending_constraints(int p_distance) {
// Build node links.
node_links.resize(nodes.size());
- for (i = 0; i < links.size(); ++i) {
- const int ia = (int)(links[i].n[0] - &nodes[0]);
- const int ib = (int)(links[i].n[1] - &nodes[0]);
+ for (Link &link : links) {
+ const int ia = (int)(link.n[0] - &nodes[0]);
+ const int ib = (int)(link.n[1] - &nodes[0]);
if (node_links[ia].find(ib) == -1) {
node_links[ia].push_back(ib);
}
@@ -649,8 +640,7 @@ void GodotSoftBody3D::generate_bending_constraints(int p_distance) {
for (uint32_t ii = 0; ii < node_links.size(); ii++) {
for (uint32_t jj = 0; jj < node_links[ii].size(); jj++) {
int k = node_links[ii][jj];
- for (uint32_t kk = 0; kk < node_links[k].size(); kk++) {
- int l = node_links[k][kk];
+ for (const int &l : node_links[k]) {
if ((int)ii != l) {
int idx_ik = k * n + ii;
int idx_kj = l * n + k;
@@ -916,8 +906,7 @@ void GodotSoftBody3D::set_drag_coefficient(real_t p_val) {
}
void GodotSoftBody3D::add_velocity(const Vector3 &p_velocity) {
- for (uint32_t i = 0, ni = nodes.size(); i < ni; ++i) {
- Node &node = nodes[i];
+ for (Node &node : nodes) {
if (node.im > 0) {
node.v += p_velocity;
}
@@ -929,26 +918,22 @@ void GodotSoftBody3D::apply_forces(const LocalVector<GodotArea3D *> &p_wind_area
return;
}
- uint32_t i, ni;
int32_t j;
real_t volume = 0.0;
const Vector3 &org = nodes[0].x;
// Iterate over faces (try not to iterate elsewhere if possible).
- for (i = 0, ni = faces.size(); i < ni; ++i) {
- const Face &face = faces[i];
-
+ for (const Face &face : faces) {
Vector3 wind_force(0, 0, 0);
// Compute volume.
volume += vec3_dot(face.n[0]->x - org, vec3_cross(face.n[1]->x - org, face.n[2]->x - org));
// Compute nodal forces from area winds.
- int wind_area_count = p_wind_areas.size();
- if (wind_area_count > 0) {
- for (j = 0; j < wind_area_count; j++) {
- wind_force += _compute_area_windforce(p_wind_areas[j], &face);
+ if (!p_wind_areas.is_empty()) {
+ for (const GodotArea3D *area : p_wind_areas) {
+ wind_force += _compute_area_windforce(area, &face);
}
for (j = 0; j < 3; j++) {
@@ -962,8 +947,7 @@ void GodotSoftBody3D::apply_forces(const LocalVector<GodotArea3D *> &p_wind_area
// Apply nodal pressure forces.
if (pressure_coefficient > CMP_EPSILON) {
real_t ivolumetp = 1.0 / Math::abs(volume) * pressure_coefficient;
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- Node &node = nodes[i];
+ for (Node &node : nodes) {
if (node.im > 0) {
node.f += node.n * (node.area * ivolumetp);
}
@@ -1048,9 +1032,7 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) {
real_t clamp_delta_v = max_displacement * inv_delta;
// Integrate.
- uint32_t i, ni;
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- Node &node = nodes[i];
+ for (Node &node : nodes) {
node.q = node.x;
Vector3 delta_v = node.f * node.im * p_delta;
for (int c = 0; c < 3; c++) {
@@ -1065,9 +1047,7 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) {
update_bounds();
// Node tree update.
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- const Node &node = nodes[i];
-
+ for (const Node &node : nodes) {
AABB node_aabb(node.x, Vector3());
node_aabb.expand_to(node.x + node.v * p_delta);
node_aabb.grow_by(collision_margin);
@@ -1088,17 +1068,13 @@ void GodotSoftBody3D::predict_motion(real_t p_delta) {
void GodotSoftBody3D::solve_constraints(real_t p_delta) {
const real_t inv_delta = 1.0 / p_delta;
- uint32_t i, ni;
-
- for (i = 0, ni = links.size(); i < ni; ++i) {
- Link &link = links[i];
+ for (Link &link : links) {
link.c3 = link.n[1]->q - link.n[0]->q;
link.c2 = 1 / (link.c3.length_squared() * link.c0);
}
// Solve velocities.
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- Node &node = nodes[i];
+ for (Node &node : nodes) {
node.x = node.q + node.v * p_delta;
}
@@ -1108,9 +1084,7 @@ void GodotSoftBody3D::solve_constraints(real_t p_delta) {
solve_links(1.0, ti);
}
const real_t vc = (1.0 - damping_coefficient) * inv_delta;
- for (i = 0, ni = nodes.size(); i < ni; ++i) {
- Node &node = nodes[i];
-
+ for (Node &node : nodes) {
node.x += node.bv * p_delta;
node.bv = Vector3();
@@ -1123,8 +1097,7 @@ void GodotSoftBody3D::solve_constraints(real_t p_delta) {
}
void GodotSoftBody3D::solve_links(real_t kst, real_t ti) {
- for (uint32_t i = 0, ni = links.size(); i < ni; ++i) {
- Link &link = links[i];
+ for (Link &link : links) {
if (link.c0 > 0) {
Node &node_a = *link.n[0];
Node &node_b = *link.n[1];
@@ -1183,9 +1156,7 @@ void GodotSoftBody3D::query_ray(const Vector3 &p_from, const Vector3 &p_to, Godo
void GodotSoftBody3D::initialize_face_tree() {
face_tree.clear();
- for (uint32_t i = 0; i < faces.size(); ++i) {
- Face &face = faces[i];
-
+ for (Face &face : faces) {
AABB face_aabb;
face_aabb.position = face.n[0]->x;
@@ -1199,9 +1170,7 @@ void GodotSoftBody3D::initialize_face_tree() {
}
void GodotSoftBody3D::update_face_tree(real_t p_delta) {
- for (uint32_t i = 0; i < faces.size(); ++i) {
- const Face &face = faces[i];
-
+ for (const Face &face : faces) {
AABB face_aabb;
const Node *node0 = face.n[0];
diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp
index c3aad22932..35f6fa023d 100644
--- a/servers/physics_3d/godot_space_3d.cpp
+++ b/servers/physics_3d/godot_space_3d.cpp
@@ -445,7 +445,7 @@ struct _RestCallbackData {
_RestResultData *other_results = nullptr;
};
-static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) {
+static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, const Vector3 &normal, void *p_userdata) {
_RestCallbackData *rd = static_cast<_RestCallbackData *>(p_userdata);
Vector3 contact_rel = p_point_B - p_point_A;
@@ -480,7 +480,7 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect
// Keep this result as separate result.
result.len = len;
result.contact = p_point_B;
- result.normal = contact_rel / len;
+ result.normal = normal;
result.object = rd->object;
result.shape = rd->shape;
result.local_shape = rd->local_shape;
@@ -499,7 +499,7 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect
rd->best_result.len = len;
rd->best_result.contact = p_point_B;
- rd->best_result.normal = contact_rel / len;
+ rd->best_result.normal = normal;
rd->best_result.object = rd->object;
rd->best_result.shape = rd->shape;
rd->best_result.local_shape = rd->local_shape;
@@ -1250,14 +1250,14 @@ GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() {
}
GodotSpace3D::GodotSpace3D() {
- body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
- body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0));
- body_time_to_sleep = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5);
- solver_iterations = GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/3d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16);
- contact_recycle_radius = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01);
- contact_max_separation = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.05);
- contact_max_allowed_penetration = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01);
- contact_bias = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8);
+ body_linear_velocity_sleep_threshold = GLOBAL_GET("physics/3d/sleep_threshold_linear");
+ body_angular_velocity_sleep_threshold = GLOBAL_GET("physics/3d/sleep_threshold_angular");
+ body_time_to_sleep = GLOBAL_GET("physics/3d/time_before_sleep");
+ solver_iterations = GLOBAL_GET("physics/3d/solver/solver_iterations");
+ contact_recycle_radius = GLOBAL_GET("physics/3d/solver/contact_recycle_radius");
+ contact_max_separation = GLOBAL_GET("physics/3d/solver/contact_max_separation");
+ contact_max_allowed_penetration = GLOBAL_GET("physics/3d/solver/contact_max_allowed_penetration");
+ contact_bias = GLOBAL_GET("physics/3d/solver/default_contact_bias");
broadphase = GodotBroadPhase3D::create_func();
broadphase->set_pair_callback(_broadphase_pair, this);
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 214de27b35..f9a8d5f156 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -811,8 +811,7 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT);
- BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE);
- BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION);
+ BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE);
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
@@ -880,6 +879,23 @@ void PhysicsServer2D::_bind_methods() {
PhysicsServer2D::PhysicsServer2D() {
singleton = this;
+
+ // World2D physics space
+ GLOBAL_DEF_BASIC("physics/2d/default_gravity", 980.0);
+ GLOBAL_DEF_BASIC("physics/2d/default_gravity_vector", Vector2(0, 1));
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), 0.1);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), 1.0);
+
+ // PhysicsServer2D
+ GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
+ GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0));
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5);
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/2d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.0);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 1.5);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 0.3);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/2d/solver/default_constraint_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.2);
}
PhysicsServer2D::~PhysicsServer2D() {
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 836ab5bd76..3e254e610e 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -286,8 +286,7 @@ public:
AREA_PARAM_GRAVITY,
AREA_PARAM_GRAVITY_VECTOR,
AREA_PARAM_GRAVITY_IS_POINT,
- AREA_PARAM_GRAVITY_DISTANCE_SCALE,
- AREA_PARAM_GRAVITY_POINT_ATTENUATION,
+ AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE,
AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE,
AREA_PARAM_LINEAR_DAMP,
AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE,
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index f1272a985d..6a163c86d2 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -976,8 +976,7 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR);
BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT);
- BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE);
- BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION);
+ BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE);
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE);
BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP);
BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE);
@@ -1048,6 +1047,22 @@ void PhysicsServer3D::_bind_methods() {
PhysicsServer3D::PhysicsServer3D() {
singleton = this;
+
+ // World3D physics space
+ GLOBAL_DEF_BASIC("physics/3d/default_gravity", 9.8);
+ GLOBAL_DEF_BASIC("physics/3d/default_gravity_vector", Vector3(0, -1, 0));
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), 0.1);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "0,100,0.001,or_greater"), 0.1);
+
+ // PhysicsServer3D
+ GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
+ GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0));
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"), 0.5);
+ GLOBAL_DEF(PropertyInfo(Variant::INT, "physics/3d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"), 16);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.05);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_allowed_penetration", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"), 0.01);
+ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "physics/3d/solver/default_contact_bias", PROPERTY_HINT_RANGE, "0,1,0.01"), 0.8);
}
PhysicsServer3D::~PhysicsServer3D() {
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index d1c644d51a..abf22e68a4 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -316,8 +316,7 @@ public:
AREA_PARAM_GRAVITY,
AREA_PARAM_GRAVITY_VECTOR,
AREA_PARAM_GRAVITY_IS_POINT,
- AREA_PARAM_GRAVITY_DISTANCE_SCALE,
- AREA_PARAM_GRAVITY_POINT_ATTENUATION,
+ AREA_PARAM_GRAVITY_POINT_UNIT_DISTANCE,
AREA_PARAM_LINEAR_DAMP_OVERRIDE_MODE,
AREA_PARAM_LINEAR_DAMP,
AREA_PARAM_ANGULAR_DAMP_OVERRIDE_MODE,
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index 2d66c225e8..aba362c956 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -126,6 +126,7 @@ public:
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override {}
virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override {}
virtual void mesh_instance_check_for_update(RID p_mesh_instance) override {}
+ virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) override {}
virtual void update_mesh_instances() override {}
/* MULTIMESH API */
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 62e1eb326d..fd36e7ac10 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -154,6 +154,7 @@ public:
virtual RID decal_instance_create(RID p_decal) override { return RID(); }
virtual void decal_instance_free(RID p_decal_instance) override {}
virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
+ virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override {}
/* RENDER TARGET */
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index 3510b415d8..b9e3c4f303 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -597,7 +597,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
Vector2 end_left;
Vector2 end_right;
- if (p_width > 1.001) {
+ if (p_width >= 0.0) {
begin_left = p_from + t;
begin_right = p_from - t;
end_left = p_to + t;
@@ -628,7 +628,7 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
// This value is empirically determined to provide good antialiasing quality
// while not making lines appear too soft.
float border_size = 1.25f;
- if (p_width < 1.0f) {
+ if (0.0f <= p_width && p_width < 1.0f) {
border_size *= p_width;
}
Vector2 dir2 = diff.normalized();
@@ -769,6 +769,49 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
}
}
+static Vector2 compute_polyline_segment_dir(const Vector<Point2> &p_points, int p_index, const Vector2 &p_prev_segment_dir) {
+ int point_count = p_points.size();
+
+ bool is_last_point = (p_index == point_count - 1);
+
+ Vector2 segment_dir;
+
+ if (is_last_point) {
+ segment_dir = p_prev_segment_dir;
+ } else {
+ segment_dir = (p_points[p_index + 1] - p_points[p_index]).normalized();
+
+ if (segment_dir.is_zero_approx()) {
+ segment_dir = p_prev_segment_dir;
+ }
+ }
+
+ return segment_dir;
+}
+
+static Vector2 compute_polyline_edge_offset_clamped(const Vector2 &p_segment_dir, const Vector2 &p_prev_segment_dir) {
+ Vector2 bisector;
+ float length = 1.0f;
+
+ bisector = (p_prev_segment_dir * p_segment_dir.length() - p_segment_dir * p_prev_segment_dir.length()).normalized();
+
+ float angle = atan2f(bisector.cross(p_prev_segment_dir), bisector.dot(p_prev_segment_dir));
+ float sin_angle = sinf(angle);
+
+ if (!Math::is_zero_approx(sin_angle) && !p_segment_dir.is_equal_approx(p_prev_segment_dir)) {
+ length = 1.0f / sin_angle;
+ length = CLAMP(length, -3.0f, 3.0f);
+ } else {
+ bisector = p_segment_dir.orthogonal();
+ }
+
+ if (bisector.is_zero_approx()) {
+ bisector = p_segment_dir.orthogonal();
+ }
+
+ return bisector * length;
+}
+
void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width, bool p_antialiased) {
ERR_FAIL_COND(p_points.size() < 2);
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
@@ -777,20 +820,68 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color color = Color(1, 1, 1, 1);
Vector<int> indices;
- int pc = p_points.size();
- int pc2 = pc * 2;
-
- Vector2 prev_t;
- int j2;
+ int point_count = p_points.size();
Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>();
ERR_FAIL_COND(!pline);
+ if (p_width < 0) {
+ if (p_antialiased) {
+ WARN_PRINT("Antialiasing is not supported for thin polylines drawn using line strips (`p_width < 0`).");
+ }
+
+ pline->primitive = RS::PRIMITIVE_LINE_STRIP;
+
+ if (p_colors.size() == 1 || p_colors.size() == point_count) {
+ pline->polygon.create(indices, p_points, p_colors);
+ } else {
+ Vector<Color> colors;
+ if (p_colors.is_empty()) {
+ colors.push_back(color);
+ } else {
+ colors.resize(point_count);
+ Color *colors_ptr = colors.ptrw();
+ for (int i = 0; i < point_count; i++) {
+ if (i < p_colors.size()) {
+ color = p_colors[i];
+ }
+ colors_ptr[i] = color;
+ }
+ }
+ pline->polygon.create(indices, p_points, colors);
+ }
+ return;
+ }
+
+ int polyline_point_count = point_count * 2;
+
+ bool loop = p_points[0].is_equal_approx(p_points[point_count - 1]);
+ Vector2 first_segment_dir;
+ Vector2 last_segment_dir;
+
+ // Search for first non-zero vector between two segments.
+ for (int i = 1; i < point_count; i++) {
+ first_segment_dir = (p_points[i] - p_points[i - 1]).normalized();
+
+ if (!first_segment_dir.is_zero_approx()) {
+ break;
+ }
+ }
+
+ // Search for last non-zero vector between two segments.
+ for (int i = point_count - 1; i >= 1; i--) {
+ last_segment_dir = (p_points[i] - p_points[i - 1]).normalized();
+
+ if (!last_segment_dir.is_zero_approx()) {
+ break;
+ }
+ }
+
PackedColorArray colors;
PackedVector2Array points;
- colors.resize(pc2);
- points.resize(pc2);
+ colors.resize(polyline_point_count);
+ points.resize(polyline_point_count);
Vector2 *points_ptr = points.ptrw();
Color *colors_ptr = colors.ptrw();
@@ -845,14 +936,14 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
PackedColorArray colors_left;
PackedVector2Array points_left;
- colors_left.resize(pc2);
- points_left.resize(pc2);
+ colors_left.resize(polyline_point_count);
+ points_left.resize(polyline_point_count);
PackedColorArray colors_right;
PackedVector2Array points_right;
- colors_right.resize(pc2);
- points_right.resize(pc2);
+ colors_right.resize(polyline_point_count);
+ points_right.resize(polyline_point_count);
Item::CommandPolygon *pline_begin = canvas_item->alloc_command<Item::CommandPolygon>();
ERR_FAIL_COND(!pline_begin);
@@ -898,79 +989,81 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_left_ptr = colors_left.ptrw();
Color *colors_right_ptr = colors_right.ptrw();
- for (int i = 0, j = 0; i < pc; i++, j += 2) {
- bool is_begin = i == 0;
- bool is_end = i == pc - 1;
+ Vector2 prev_segment_dir;
+ for (int i = 0; i < point_count; i++) {
+ bool is_first_point = (i == 0);
+ bool is_last_point = (i == point_count - 1);
- Vector2 t;
- Vector2 end_border;
- Vector2 begin_border;
- if (is_end) {
- t = prev_t;
- end_border = (p_points[i] - p_points[i - 1]).normalized() * border_size;
- } else {
- t = (p_points[i + 1] - p_points[i]).normalized().orthogonal();
- if (is_begin) {
- prev_t = t;
- begin_border = (p_points[i] - p_points[i + 1]).normalized() * border_size;
- }
+ Vector2 segment_dir = compute_polyline_segment_dir(p_points, i, prev_segment_dir);
+ if (is_first_point && loop) {
+ prev_segment_dir = last_segment_dir;
+ } else if (is_last_point && loop) {
+ prev_segment_dir = first_segment_dir;
}
- j2 = j + 1;
+ Vector2 base_edge_offset;
+ if (is_first_point && !loop) {
+ base_edge_offset = first_segment_dir.orthogonal();
+ } else if (is_last_point && !loop) {
+ base_edge_offset = last_segment_dir.orthogonal();
+ } else {
+ base_edge_offset = compute_polyline_edge_offset_clamped(segment_dir, prev_segment_dir);
+ }
- Vector2 dir = (t + prev_t).normalized();
- Vector2 tangent = dir * p_width * 0.5;
- Vector2 border = dir * border_size;
+ Vector2 edge_offset = base_edge_offset * (p_width * 0.5f);
+ Vector2 border = base_edge_offset * border_size;
Vector2 pos = p_points[i];
- points_ptr[j] = pos + tangent;
- points_ptr[j2] = pos - tangent;
+ points_ptr[i * 2 + 0] = pos + edge_offset;
+ points_ptr[i * 2 + 1] = pos - edge_offset;
- points_left_ptr[j] = pos + tangent + border;
- points_left_ptr[j2] = pos + tangent;
+ points_left_ptr[i * 2 + 0] = pos + edge_offset + border;
+ points_left_ptr[i * 2 + 1] = pos + edge_offset;
- points_right_ptr[j] = pos - tangent;
- points_right_ptr[j2] = pos - tangent - border;
+ points_right_ptr[i * 2 + 0] = pos - edge_offset;
+ points_right_ptr[i * 2 + 1] = pos - edge_offset - border;
if (i < p_colors.size()) {
color = p_colors[i];
color2 = Color(color.r, color.g, color.b, 0);
}
- colors_ptr[j] = color;
- colors_ptr[j2] = color;
+ colors_ptr[i * 2 + 0] = color;
+ colors_ptr[i * 2 + 1] = color;
+
+ colors_left_ptr[i * 2 + 0] = color2;
+ colors_left_ptr[i * 2 + 1] = color;
- colors_left_ptr[j] = color2;
- colors_left_ptr[j2] = color;
+ colors_right_ptr[i * 2 + 0] = color;
+ colors_right_ptr[i * 2 + 1] = color2;
- colors_right_ptr[j] = color;
- colors_right_ptr[j2] = color2;
+ if (is_first_point) {
+ Vector2 begin_border = loop ? Vector2() : -segment_dir * border_size;
- if (is_begin) {
- points_begin_ptr[0] = pos + tangent + begin_border;
- points_begin_ptr[1] = pos - tangent + begin_border;
- points_begin_ptr[2] = pos + tangent;
- points_begin_ptr[3] = pos - tangent;
+ points_begin_ptr[0] = pos + edge_offset + begin_border;
+ points_begin_ptr[1] = pos - edge_offset + begin_border;
+ points_begin_ptr[2] = pos + edge_offset;
+ points_begin_ptr[3] = pos - edge_offset;
colors_begin_ptr[0] = color2;
colors_begin_ptr[1] = color2;
colors_begin_ptr[2] = color;
colors_begin_ptr[3] = color;
- points_begin_left_corner_ptr[0] = pos - tangent - border;
- points_begin_left_corner_ptr[1] = pos - tangent + begin_border - border;
- points_begin_left_corner_ptr[2] = pos - tangent;
- points_begin_left_corner_ptr[3] = pos - tangent + begin_border;
+ points_begin_left_corner_ptr[0] = pos - edge_offset - border;
+ points_begin_left_corner_ptr[1] = pos - edge_offset + begin_border - border;
+ points_begin_left_corner_ptr[2] = pos - edge_offset;
+ points_begin_left_corner_ptr[3] = pos - edge_offset + begin_border;
colors_begin_left_corner_ptr[0] = color2;
colors_begin_left_corner_ptr[1] = color2;
colors_begin_left_corner_ptr[2] = color;
colors_begin_left_corner_ptr[3] = color2;
- points_begin_right_corner_ptr[0] = pos + tangent + begin_border;
- points_begin_right_corner_ptr[1] = pos + tangent + begin_border + border;
- points_begin_right_corner_ptr[2] = pos + tangent;
- points_begin_right_corner_ptr[3] = pos + tangent + border;
+ points_begin_right_corner_ptr[0] = pos + edge_offset + begin_border;
+ points_begin_right_corner_ptr[1] = pos + edge_offset + begin_border + border;
+ points_begin_right_corner_ptr[2] = pos + edge_offset;
+ points_begin_right_corner_ptr[3] = pos + edge_offset + border;
colors_begin_right_corner_ptr[0] = color2;
colors_begin_right_corner_ptr[1] = color2;
@@ -978,31 +1071,33 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
colors_begin_right_corner_ptr[3] = color2;
}
- if (is_end) {
- points_end_ptr[0] = pos + tangent + end_border;
- points_end_ptr[1] = pos - tangent + end_border;
- points_end_ptr[2] = pos + tangent;
- points_end_ptr[3] = pos - tangent;
+ if (is_last_point) {
+ Vector2 end_border = loop ? Vector2() : prev_segment_dir * border_size;
+
+ points_end_ptr[0] = pos + edge_offset + end_border;
+ points_end_ptr[1] = pos - edge_offset + end_border;
+ points_end_ptr[2] = pos + edge_offset;
+ points_end_ptr[3] = pos - edge_offset;
colors_end_ptr[0] = color2;
colors_end_ptr[1] = color2;
colors_end_ptr[2] = color;
colors_end_ptr[3] = color;
- points_end_left_corner_ptr[0] = pos - tangent - border;
- points_end_left_corner_ptr[1] = pos - tangent + end_border - border;
- points_end_left_corner_ptr[2] = pos - tangent;
- points_end_left_corner_ptr[3] = pos - tangent + end_border;
+ points_end_left_corner_ptr[0] = pos - edge_offset - border;
+ points_end_left_corner_ptr[1] = pos - edge_offset + end_border - border;
+ points_end_left_corner_ptr[2] = pos - edge_offset;
+ points_end_left_corner_ptr[3] = pos - edge_offset + end_border;
colors_end_left_corner_ptr[0] = color2;
colors_end_left_corner_ptr[1] = color2;
colors_end_left_corner_ptr[2] = color;
colors_end_left_corner_ptr[3] = color2;
- points_end_right_corner_ptr[0] = pos + tangent + end_border;
- points_end_right_corner_ptr[1] = pos + tangent + end_border + border;
- points_end_right_corner_ptr[2] = pos + tangent;
- points_end_right_corner_ptr[3] = pos + tangent + border;
+ points_end_right_corner_ptr[0] = pos + edge_offset + end_border;
+ points_end_right_corner_ptr[1] = pos + edge_offset + end_border + border;
+ points_end_right_corner_ptr[2] = pos + edge_offset;
+ points_end_right_corner_ptr[3] = pos + edge_offset + border;
colors_end_right_corner_ptr[0] = color2;
colors_end_right_corner_ptr[1] = color2;
@@ -1010,7 +1105,7 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
colors_end_right_corner_ptr[3] = color2;
}
- prev_t = t;
+ prev_segment_dir = segment_dir;
}
pline_begin->primitive = RS::PRIMITIVE_TRIANGLE_STRIP;
@@ -1039,33 +1134,41 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
} else {
// Makes a single triangle strip for drawing the line.
- for (int i = 0, j = 0; i < pc; i++, j += 2) {
- Vector2 t;
- if (i == pc - 1) {
- t = prev_t;
- } else {
- t = (p_points[i + 1] - p_points[i]).normalized().orthogonal();
- if (i == 0) {
- prev_t = t;
- }
+ Vector2 prev_segment_dir;
+ for (int i = 0; i < point_count; i++) {
+ bool is_first_point = (i == 0);
+ bool is_last_point = (i == point_count - 1);
+
+ Vector2 segment_dir = compute_polyline_segment_dir(p_points, i, prev_segment_dir);
+ if (is_first_point && loop) {
+ prev_segment_dir = last_segment_dir;
+ } else if (is_last_point && loop) {
+ prev_segment_dir = first_segment_dir;
}
- j2 = j + 1;
+ Vector2 base_edge_offset;
+ if (is_first_point && !loop) {
+ base_edge_offset = first_segment_dir.orthogonal();
+ } else if (is_last_point && !loop) {
+ base_edge_offset = last_segment_dir.orthogonal();
+ } else {
+ base_edge_offset = compute_polyline_edge_offset_clamped(segment_dir, prev_segment_dir);
+ }
- Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5;
+ Vector2 edge_offset = base_edge_offset * (p_width * 0.5f);
Vector2 pos = p_points[i];
- points_ptr[j] = pos + tangent;
- points_ptr[j2] = pos - tangent;
+ points_ptr[i * 2 + 0] = pos + edge_offset;
+ points_ptr[i * 2 + 1] = pos - edge_offset;
if (i < p_colors.size()) {
color = p_colors[i];
}
- colors_ptr[j] = color;
- colors_ptr[j2] = color;
+ colors_ptr[i * 2 + 0] = color;
+ colors_ptr[i * 2 + 1] = color;
- prev_t = t;
+ prev_segment_dir = segment_dir;
}
}
@@ -1077,7 +1180,7 @@ void RendererCanvasCull::canvas_item_add_multiline(RID p_item, const Vector<Poin
ERR_FAIL_COND(p_points.size() < 2);
// TODO: `canvas_item_add_line`(`multiline`, `polyline`) share logic, should factor out.
- if (p_width <= 1) {
+ if (p_width < 0) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1133,20 +1236,23 @@ void RendererCanvasCull::canvas_item_add_circle(RID p_item, const Point2 &p_pos,
static const int circle_points = 64;
points.resize(circle_points);
+ Vector2 *points_ptr = points.ptrw();
const real_t circle_point_step = Math_TAU / circle_points;
for (int i = 0; i < circle_points; i++) {
float angle = i * circle_point_step;
- points.write[i].x = Math::cos(angle) * p_radius;
- points.write[i].y = Math::sin(angle) * p_radius;
- points.write[i] += p_pos;
+ points_ptr[i].x = Math::cos(angle) * p_radius;
+ points_ptr[i].y = Math::sin(angle) * p_radius;
+ points_ptr[i] += p_pos;
}
+
indices.resize((circle_points - 2) * 3);
+ int *indices_ptr = indices.ptrw();
for (int i = 0; i < circle_points - 2; i++) {
- indices.write[i * 3 + 0] = 0;
- indices.write[i * 3 + 1] = i + 1;
- indices.write[i * 3 + 2] = i + 2;
+ indices_ptr[i * 3 + 0] = 0;
+ indices_ptr[i * 3 + 1] = i + 1;
+ indices_ptr[i * 3 + 2] = i + 2;
}
Vector<Color> color;
@@ -1313,7 +1419,7 @@ void RendererCanvasCull::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_r
style->axis_y = p_y_axis_mode;
}
-void RendererCanvasCull::canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width) {
+void RendererCanvasCull::canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) {
uint32_t pc = p_points.size();
ERR_FAIL_COND(pc == 0 || pc > 4);
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 4d0be48cc0..1106fc4f1e 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -221,9 +221,9 @@ public:
void canvas_item_set_update_when_visible(RID p_item, bool p_update);
- void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false);
- void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false);
- void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
+ void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false);
+ void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false);
+ void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0);
void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
@@ -231,7 +231,7 @@ public:
void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0);
void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
- void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0);
+ void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture);
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID());
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1);
void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID());
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 73a0c652a4..959a752fba 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -74,7 +74,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
cluster_debug.shader_pipeline = RD::get_singleton()->compute_pipeline_create(cluster_debug.shader);
}
- { // SPHERE
+ { // Sphere mesh data.
static const uint32_t icosphere_vertex_count = 42;
static const float icosphere_vertices[icosphere_vertex_count * 3] = {
0, 0, -1, 0.7236073, -0.5257253, -0.4472195, -0.276388, -0.8506492, -0.4472199, -0.8944262, 0, -0.4472156, -0.276388, 0.8506492, -0.4472199, 0.7236073, 0.5257253, -0.4472195, 0.276388, -0.8506492, 0.4472199, -0.7236073, -0.5257253, 0.4472195, -0.7236073, 0.5257253, 0.4472195, 0.276388, 0.8506492, 0.4472199, 0.8944262, 0, 0.4472156, 0, 0, 1, -0.1624555, -0.4999952, -0.8506544, 0.4253227, -0.3090114, -0.8506542, 0.2628688, -0.8090116, -0.5257377, 0.8506479, 0, -0.5257359, 0.4253227, 0.3090114, -0.8506542, -0.5257298, 0, -0.8506517, -0.6881894, -0.4999969, -0.5257362, -0.1624555, 0.4999952, -0.8506544, -0.6881894, 0.4999969, -0.5257362, 0.2628688, 0.8090116, -0.5257377, 0.9510579, -0.3090126, 0, 0.9510579, 0.3090126, 0, 0, -1, 0, 0.5877856, -0.8090167, 0, -0.9510579, -0.3090126, 0, -0.5877856, -0.8090167, 0, -0.5877856, 0.8090167, 0, -0.9510579, 0.3090126, 0, 0.5877856, 0.8090167, 0, 0, 1, 0, 0.6881894, -0.4999969, 0.5257362, -0.2628688, -0.8090116, 0.5257377, -0.8506479, 0, 0.5257359, -0.2628688, 0.8090116, 0.5257377, 0.6881894, 0.4999969, 0.5257362, 0.1624555, -0.4999952, 0.8506544, 0.5257298, 0, 0.8506517, -0.4253227, -0.3090114, 0.8506542, -0.4253227, 0.3090114, 0.8506542, 0.1624555, 0.4999952, 0.8506544
@@ -118,7 +118,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
sphere_overfit = 1.0 / min_d;
}
- { // CONE
+ { // Cone mesh data.
static const uint32_t cone_vertex_count = 99;
static const float cone_vertices[cone_vertex_count * 3] = {
0, 1, -1, 0.1950903, 0.9807853, -1, 0.3826835, 0.9238795, -1, 0.5555703, 0.8314696, -1, 0.7071068, 0.7071068, -1, 0.8314697, 0.5555702, -1, 0.9238795, 0.3826834, -1, 0.9807853, 0.1950903, -1, 1, 0, -1, 0.9807853, -0.1950902, -1, 0.9238796, -0.3826833, -1, 0.8314697, -0.5555702, -1, 0.7071068, -0.7071068, -1, 0.5555702, -0.8314697, -1, 0.3826833, -0.9238796, -1, 0.1950901, -0.9807853, -1, -3.25841e-7, -1, -1, -0.1950907, -0.9807852, -1, -0.3826839, -0.9238793, -1, -0.5555707, -0.8314693, -1, -0.7071073, -0.7071063, -1, -0.83147, -0.5555697, -1, -0.9238799, -0.3826827, -1, 0, 0, 0, -0.9807854, -0.1950894, -1, -1, 9.65599e-7, -1, -0.9807851, 0.1950913, -1, -0.9238791, 0.3826845, -1, -0.8314689, 0.5555713, -1, -0.7071059, 0.7071077, -1, -0.5555691, 0.8314704, -1, -0.3826821, 0.9238801, -1, -0.1950888, 0.9807856, -1
@@ -172,7 +172,7 @@ ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() {
cone_overfit = 1.0 / min_d;
}
- { // BOX
+ { // Box mesh data.
static const uint32_t box_vertex_count = 8;
static const float box_vertices[box_vertex_count * 3] = {
-1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1
@@ -219,8 +219,9 @@ ClusterBuilderSharedDataRD::~ClusterBuilderSharedDataRD() {
void ClusterBuilderRD::_clear() {
if (cluster_buffer.is_null()) {
- return; //nothing to clear
+ return;
}
+
RD::get_singleton()->free(cluster_buffer);
RD::get_singleton()->free(cluster_render_buffer);
RD::get_singleton()->free(element_buffer);
@@ -254,7 +255,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
cluster_screen_size.height = (p_screen_size.height - 1) / cluster_size + 1;
max_elements_by_type = p_max_elements;
- if (max_elements_by_type % 32) { //need to be 32 aligned
+ if (max_elements_by_type % 32) { // Needs to be aligned to 32.
max_elements_by_type += 32 - (max_elements_by_type % 32);
}
@@ -264,7 +265,8 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
uint32_t element_tag_bits_size = render_element_max / 32;
uint32_t element_tag_depth_bits_size = render_element_max;
- cluster_render_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (element_tag_bits_size + element_tag_depth_bits_size) * 4; // tag bits (element was used) and tag depth (depth range in which it was used)
+
+ cluster_render_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (element_tag_bits_size + element_tag_depth_bits_size) * 4; // Tag bits (element was used) and tag depth (depth range in which it was used).
cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size);
cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size);
@@ -379,9 +381,9 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projecti
projection = p_cam_projection;
z_near = projection.get_z_near();
z_far = projection.get_z_far();
- orthogonal = p_cam_projection.is_orthogonal();
+ camera_orthogonal = p_cam_projection.is_orthogonal();
adjusted_projection = projection;
- if (!orthogonal) {
+ if (!camera_orthogonal) {
adjusted_projection.adjust_perspective_znear(0.0001);
}
@@ -390,7 +392,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projecti
projection = correction * projection;
adjusted_projection = correction * adjusted_projection;
- //reset counts
+ // Reset counts.
render_element_count = 0;
for (uint32_t i = 0; i < ELEMENT_TYPE_MAX; i++) {
cluster_count_by_type[i] = 0;
@@ -402,14 +404,14 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_command_begin_label("Bake Light Cluster");
- //clear cluster buffer
+ // Clear cluster buffer.
RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
if (render_element_count > 0) {
- //clear render buffer
+ // Clear render buffer.
RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size, RD::BARRIER_MASK_RASTER);
- { //fill state uniform
+ { // Fill state uniform.
StateUniform state;
@@ -425,13 +427,13 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
}
- //update instances
+ // Update instances.
RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
RENDER_TIMESTAMP("Render 3D Cluster Elements");
- //render elements
+ // Render elements.
{
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD);
ClusterBuilderSharedDataRD::ClusterRender::PushConstant push_constant = {};
@@ -447,8 +449,16 @@ void ClusterBuilderRD::bake_cluster() {
RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array);
} break;
case ELEMENT_TYPE_SPOT_LIGHT: {
- RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->cone_vertex_array);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->cone_index_array);
+ // If the spot angle is above a certain threshold, use a sphere instead of a cone for building the clusters
+ // since the cone gets too flat/large (spot angle close to 90 degrees) or
+ // can't even cover the affected area of the light (spot angle above 90 degrees).
+ if (render_elements[i].has_wide_spot_angle) {
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->sphere_vertex_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array);
+ } else {
+ RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->cone_vertex_array);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->cone_index_array);
+ }
} break;
case ELEMENT_TYPE_DECAL:
case ELEMENT_TYPE_REFLECTION_PROBE: {
@@ -465,7 +475,7 @@ void ClusterBuilderRD::bake_cluster() {
}
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE);
}
- //store elements
+ // Store elements.
RENDER_TIMESTAMP("Pack 3D Cluster Elements");
{
@@ -509,7 +519,7 @@ void ClusterBuilderRD::debug(ElementType p_element) {
push_constant.cluster_screen_size[1] = cluster_screen_size.y;
push_constant.cluster_shift = get_shift_from_power_of_2(cluster_size);
push_constant.cluster_type = p_element;
- push_constant.orthogonal = orthogonal;
+ push_constant.orthogonal = camera_orthogonal;
push_constant.z_far = z_far;
push_constant.z_near = z_near;
push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32;
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index 0b20a5d7ee..a13e6c8172 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -43,13 +43,13 @@ class ClusterBuilderSharedDataRD {
RID sphere_vertex_array;
RID sphere_index_buffer;
RID sphere_index_array;
- float sphere_overfit = 0.0; //because an icosphere is not a perfect sphere, we need to enlarge it to cover the sphere area
+ float sphere_overfit = 0.0; // Because an icosphere is not a perfect sphere, we need to enlarge it to cover the sphere area.
RID cone_vertex_buffer;
RID cone_vertex_array;
RID cone_index_buffer;
RID cone_index_array;
- float cone_overfit = 0.0; //because an cone mesh is not a perfect sphere, we need to enlarge it to cover the actual cone area
+ float cone_overfit = 0.0; // Because an cone mesh is not a perfect cone, we need to enlarge it to cover the actual cone area.
RID box_vertex_buffer;
RID box_vertex_array;
@@ -73,6 +73,7 @@ class ClusterBuilderSharedDataRD {
ClusterRenderShaderRD cluster_render_shader;
RID shader_version;
RID shader;
+
enum PipelineVersion {
PIPELINE_NORMAL,
PIPELINE_MSAA,
@@ -85,10 +86,11 @@ class ClusterBuilderSharedDataRD {
struct ClusterStore {
struct PushConstant {
uint32_t cluster_render_data_size; // how much data for a single cluster takes
- uint32_t max_render_element_count_div_32; //divided by 32
+ uint32_t max_render_element_count_div_32; // divided by 32
uint32_t cluster_screen_size[2];
- uint32_t render_element_count_div_32; //divided by 32
- uint32_t max_cluster_element_count_div_32; //divided by 32
+ uint32_t render_element_count_div_32; // divided by 32
+ uint32_t max_cluster_element_count_div_32; // divided by 32
+
uint32_t pad1;
uint32_t pad2;
};
@@ -111,6 +113,7 @@ class ClusterBuilderSharedDataRD {
uint32_t orthogonal;
uint32_t max_cluster_element_count_div_32;
+
uint32_t pad1;
uint32_t pad2;
};
@@ -128,6 +131,8 @@ public:
class ClusterBuilderRD {
public:
+ static constexpr float WIDE_SPOT_ANGLE_THRESHOLD_DEG = 60.0f;
+
enum LightType {
LIGHT_TYPE_OMNI,
LIGHT_TYPE_SPOT
@@ -144,21 +149,20 @@ public:
ELEMENT_TYPE_DECAL,
ELEMENT_TYPE_REFLECTION_PROBE,
ELEMENT_TYPE_MAX,
-
};
private:
ClusterBuilderSharedDataRD *shared = nullptr;
struct RenderElementData {
- uint32_t type; //0-4
+ uint32_t type; // 0-4
uint32_t touches_near;
uint32_t touches_far;
uint32_t original_index;
- float transform_inv[12]; //transposed transform for less space
+ float transform_inv[12]; // Transposed transform for less space.
float scale[3];
- uint32_t pad;
- };
+ uint32_t has_wide_spot_angle;
+ }; // Keep aligned to 32 bytes.
uint32_t cluster_count_by_type[ELEMENT_TYPE_MAX] = {};
uint32_t max_elements_by_type = 0;
@@ -172,7 +176,7 @@ private:
Projection projection;
float z_far = 0;
float z_near = 0;
- bool orthogonal = false;
+ bool camera_orthogonal = false;
enum Divisor {
DIVISOR_1,
@@ -188,26 +192,27 @@ private:
Size2i cluster_screen_size;
RID framebuffer;
- RID cluster_render_buffer; //used for creating
- RID cluster_buffer; //used for rendering
- RID element_buffer; //used for storing, to hint element touches far plane or near plane
+ RID cluster_render_buffer; // Used for creating.
+ RID cluster_buffer; // Used for rendering.
+ RID element_buffer; // Used for storing, to hint element touches far plane or near plane.
uint32_t cluster_render_buffer_size = 0;
uint32_t cluster_buffer_size = 0;
RID cluster_render_uniform_set;
RID cluster_store_uniform_set;
- //persistent data
+ // Persistent data.
void _clear();
struct StateUniform {
float projection[16];
float inv_z_far;
- uint32_t screen_to_clusters_shift; // shift to obtain coordinates in block indices
- uint32_t cluster_screen_width; //
- uint32_t cluster_data_size; // how much data for a single cluster takes
+ uint32_t screen_to_clusters_shift; // Shift to obtain coordinates in block indices.
+ uint32_t cluster_screen_width;
+ uint32_t cluster_data_size; // How much data is needed for a single cluster.
uint32_t cluster_depth_offset;
+
uint32_t pad0;
uint32_t pad1;
uint32_t pad2;
@@ -224,10 +229,10 @@ public:
_FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {
if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
if (p_type == LIGHT_TYPE_SPOT && cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
RenderElementData &e = render_elements[render_element_count];
@@ -242,15 +247,14 @@ public:
radius *= p_radius;
if (p_type == LIGHT_TYPE_OMNI) {
- radius *= shared->sphere_overfit; // overfit icosphere
+ radius *= shared->sphere_overfit; // Overfit icosphere.
- //omni
float depth = -xform.origin.z;
- if (orthogonal) {
+ if (camera_orthogonal) {
e.touches_near = (depth - radius) < z_near;
} else {
- //contains camera inside light
- float radius2 = radius * shared->sphere_overfit; // overfit again for outer size (camera may be outside actual sphere but behind an icosphere vertex)
+ // Contains camera inside light.
+ float radius2 = radius * shared->sphere_overfit; // Overfit again for outer size (camera may be outside actual sphere but behind an icosphere vertex)
e.touches_near = xform.origin.length_squared() < radius2 * radius2;
}
@@ -265,12 +269,11 @@ public:
cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++;
- } else {
- //spot
- radius *= shared->cone_overfit; // overfit icosphere
+ } else /*LIGHT_TYPE_SPOT */ {
+ radius *= shared->cone_overfit; // Overfit icosphere
real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius;
- //approximate, probably better to use a cone support function
+ // Approximate, probably better to use a cone support function.
float max_d = -1e20;
float min_d = 1e20;
#define CONE_MINMAX(m_x, m_y) \
@@ -285,14 +288,13 @@ public:
CONE_MINMAX(-1, -1);
CONE_MINMAX(1, -1);
- if (orthogonal) {
+ if (camera_orthogonal) {
e.touches_near = min_d < z_near;
} else {
- //contains camera inside light
Plane base_plane(-xform.basis.get_column(Vector3::AXIS_Z), xform.origin);
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
- //inside, check angle
+ // Contains camera inside light, check angle.
float angle = Math::rad_to_deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z))));
e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit
} else {
@@ -302,12 +304,23 @@ public:
e.touches_far = max_d > z_far;
- e.scale[0] = len * shared->cone_overfit;
- e.scale[1] = len * shared->cone_overfit;
- e.scale[2] = radius;
+ // If the spot angle is above the threshold, use a sphere instead of a cone for building the clusters
+ // since the cone gets too flat/large (spot angle close to 90 degrees) or
+ // can't even cover the affected area of the light (spot angle above 90 degrees).
+ if (p_spot_aperture > WIDE_SPOT_ANGLE_THRESHOLD_DEG) {
+ e.scale[0] = radius;
+ e.scale[1] = radius;
+ e.scale[2] = radius;
+ e.has_wide_spot_angle = true;
+ } else {
+ e.scale[0] = len * shared->cone_overfit;
+ e.scale[1] = len * shared->cone_overfit;
+ e.scale[2] = radius;
+ e.has_wide_spot_angle = false;
+ }
e.type = ELEMENT_TYPE_SPOT_LIGHT;
- e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; //use omni since they share index
+ e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; // Use omni light since they share index.
RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
@@ -319,16 +332,16 @@ public:
_FORCE_INLINE_ void add_box(BoxType p_box_type, const Transform3D &p_transform, const Vector3 &p_half_extents) {
if (p_box_type == BOX_TYPE_DECAL && cluster_count_by_type[ELEMENT_TYPE_DECAL] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
if (p_box_type == BOX_TYPE_REFLECTION_PROBE && cluster_count_by_type[ELEMENT_TYPE_REFLECTION_PROBE] == max_elements_by_type) {
- return; //max number elements reached
+ return; // Max number elements reached.
}
RenderElementData &e = render_elements[render_element_count];
Transform3D xform = view_xform * p_transform;
- //extract scale and scale the matrix by it, makes things simpler
+ // Extract scale and scale the matrix by it, makes things simpler.
Vector3 scale = p_half_extents;
for (uint32_t i = 0; i < 3; i++) {
float s = xform.basis.rows[i].length();
@@ -339,10 +352,10 @@ public:
float box_depth = Math::abs(xform.basis.xform_inv(Vector3(0, 0, -1)).dot(scale));
float depth = -xform.origin.z;
- if (orthogonal) {
+ if (camera_orthogonal) {
e.touches_near = depth - box_depth < z_near;
} else {
- //contains camera inside box
+ // Contains camera inside box.
Vector3 inside = xform.xform_inv(Vector3(0, 0, 0)).abs();
e.touches_near = inside.x < scale.x && inside.y < scale.y && inside.z < scale.z;
}
diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index a52716cd78..08133bf8d6 100644
--- a/servers/rendering/renderer_rd/environment/gi.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -540,9 +540,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
occlusion_texture = RD::get_singleton()->texture_create_shared(tv, occlusion_data);
}
- for (uint32_t i = 0; i < cascades.size(); i++) {
- SDFGI::Cascade &cascade = cascades[i];
-
+ for (SDFGI::Cascade &cascade : cascades) {
/* 3D Textures */
cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
@@ -743,9 +741,7 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
}
//direct light
- for (uint32_t i = 0; i < cascades.size(); i++) {
- SDFGI::Cascade &cascade = cascades[i];
-
+ for (SDFGI::Cascade &cascade : cascades) {
Vector<RD::Uniform> uniforms;
{
RD::Uniform u;
@@ -1134,8 +1130,7 @@ void GI::SDFGI::free_data() {
}
GI::SDFGI::~SDFGI() {
- for (uint32_t i = 0; i < cascades.size(); i++) {
- const SDFGI::Cascade &c = cascades[i];
+ for (const SDFGI::Cascade &c : cascades) {
RD::get_singleton()->free(c.light_data);
RD::get_singleton()->free(c.light_aniso_0_tex);
RD::get_singleton()->free(c.light_aniso_1_tex);
@@ -1198,8 +1193,7 @@ void GI::SDFGI::update(RID p_env, const Vector3 &p_world_position) {
int32_t drag_margin = (cascade_size / SDFGI::PROBE_DIVISOR) / 2;
- for (uint32_t i = 0; i < cascades.size(); i++) {
- SDFGI::Cascade &cascade = cascades[i];
+ for (SDFGI::Cascade &cascade : cascades) {
cascade.dirty_regions = Vector3i();
Vector3 probe_half_size = Vector3(1, 1, 1) * cascade.cell_size * float(cascade_size / SDFGI::PROBE_DIVISOR) * 0.5;
diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 863e8d6c15..7fff349b3c 100644
--- a/servers/rendering/renderer_rd/environment/sky.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -347,7 +347,10 @@ void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bo
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
tf.array_layers = 6;
tf.mipmaps = p_low_quality ? 7 : mipmaps - 1;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
+ }
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
@@ -571,7 +574,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1; // half res
if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
- if (reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) {
+ if (reflection.layers.size() && reflection.layers[0].views.size() >= 2 && reflection.layers[0].views[1].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) {
u.append_id(reflection.layers[0].views[1]);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
@@ -591,7 +594,7 @@ RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shade
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2; // quarter res
if (p_version >= SKY_TEXTURE_SET_CUBEMAP) {
- if (reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) {
+ if (reflection.layers.size() && reflection.layers[0].views.size() >= 3 && reflection.layers[0].views[2].is_valid() && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) {
u.append_id(reflection.layers[0].views[2]);
} else {
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
@@ -1085,8 +1088,8 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
sky->reflection.dirty = true;
}
+ sky_scene_state.ubo.directional_light_count = 0;
if (shader_data->uses_light) {
- sky_scene_state.ubo.directional_light_count = 0;
// Run through the list of lights in the scene and pick out the Directional Lights.
// This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called
// after the depth prepass, but this runs before the depth prepass
@@ -1320,7 +1323,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
// Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader.
- if (shader_data->uses_quarter_res) {
+ if (shader_data->uses_quarter_res && roughness_layers >= 3) {
RD::get_singleton()->draw_command_begin_label("Render Sky to Quarter Res Cubemap");
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES];
@@ -1337,9 +1340,11 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
+ } else if (shader_data->uses_quarter_res && roughness_layers < 3) {
+ ERR_PRINT_ED("Cannot use quarter res buffer in sky shader when roughness layers is less than 3. Please increase rendering/reflections/sky_reflections/roughness_layers.");
}
- if (shader_data->uses_half_res) {
+ if (shader_data->uses_half_res && roughness_layers >= 2) {
RD::get_singleton()->draw_command_begin_label("Render Sky to Half Res Cubemap");
PipelineCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES];
@@ -1356,6 +1361,8 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
+ } else if (shader_data->uses_half_res && roughness_layers < 2) {
+ ERR_PRINT_ED("Cannot use half res buffer in sky shader when roughness layers is less than 2. Please increase rendering/reflections/sky_reflections/roughness_layers.");
}
RD::DrawListID cubemap_draw_list;
@@ -1627,7 +1634,10 @@ void SkyRD::update_dirty_skys() {
tf.mipmaps = mipmaps;
tf.width = w;
tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
+ }
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
@@ -1642,7 +1652,10 @@ void SkyRD::update_dirty_skys() {
tf.mipmaps = MIN(mipmaps, layers);
tf.width = w;
tf.height = h;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ if (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage()) {
+ tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
+ }
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
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 93c741fd34..2e844269e3 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -667,7 +667,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
scene_state.ubo.ss_effects_flags = 0;
- } else if (is_environment(p_render_data->environment)) {
+ } else if (p_render_data->reflection_probe.is_null() && is_environment(p_render_data->environment)) {
scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment);
scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment);
uint32_t ss_flags = 0;
@@ -1365,8 +1365,8 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
}
//cube shadows are rendered in their own way
- for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info);
+ 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);
}
if (p_render_data->directional_shadows.size()) {
@@ -1480,7 +1480,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo
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.affine_inverse());
+ 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;
@@ -1550,16 +1550,18 @@ void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buf
void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- Ref<RenderSceneBuffersRD> rb;
+ ERR_FAIL_NULL(p_render_data);
+
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
Ref<RenderBufferDataForwardClustered> rb_data;
- if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = p_render_data->render_buffers;
- if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
- // Our forward clustered custom data buffer will only be available when we're rendering our normal view.
- // This will not be available when rendering reflection probes.
- rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
- }
+ if (rb->has_custom_data(RB_SCOPE_FORWARD_CLUSTERED)) {
+ // Our forward clustered custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
}
+ bool is_reflection_probe = p_render_data->reflection_probe.is_valid();
+
static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
//first of all, make a new render pass
@@ -1588,18 +1590,16 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
p_render_data->voxel_gi_count = 0;
- if (rb.is_valid()) {
- if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
- Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
- if (sdfgi.is_valid()) {
- sdfgi->update_cascades();
- sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data);
- sdfgi->update_light();
- }
+ if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ if (sdfgi.is_valid()) {
+ sdfgi->update_cascades();
+ sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data);
+ sdfgi->update_light();
}
-
- gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
}
+
+ gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
} else {
ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
current_cluster_builder = nullptr;
@@ -1618,7 +1618,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
// check if we need motion vectors
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
p_render_data->scene_data->calculate_motion_vectors = true;
- } else if (rb.is_valid() && rb->get_use_taa()) {
+ } else if (!is_reflection_probe && rb->get_use_taa()) {
p_render_data->scene_data->calculate_motion_vectors = true;
} else {
p_render_data->scene_data->calculate_motion_vectors = false;
@@ -1641,9 +1641,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sdfgi = false;
bool using_voxelgi = false;
bool reverse_cull = p_render_data->scene_data->cam_transform.basis.determinant() < 0;
- bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment);
+ bool using_ssil = !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment);
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
@@ -1657,7 +1657,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
reverse_cull = true; // for some reason our views are inverted
- } else if (rb.is_valid()) {
+ } else {
screen_size = rb->get_internal_size();
if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
@@ -1685,8 +1685,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
color_only_framebuffer = rb_data->get_color_only_fb();
- } else {
- ERR_FAIL(); //bug?
}
p_render_data->scene_data->emissive_exposure_normalization = -1.0;
@@ -1695,7 +1693,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform);
_setup_voxelgis(*p_render_data->voxel_gi_instances);
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
@@ -1707,7 +1705,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_end_label();
- if (rb.is_valid() && !p_render_data->reflection_probe.is_valid()) {
+ if (!is_reflection_probe) {
if (using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
} else if (p_render_data->environment.is_valid()) {
@@ -1739,7 +1737,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
}
- bool using_sss = rb_data.is_valid() && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
+ bool using_sss = rb_data.is_valid() && !is_reflection_probe && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
if (using_sss && !using_separate_specular) {
using_separate_specular = true;
@@ -1772,7 +1770,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1782,7 +1780,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color.r *= bg_energy_multiplier;
clear_color.g *= bg_energy_multiplier;
clear_color.b *= bg_energy_multiplier;
- if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
+ if ((rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1791,7 +1789,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
draw_sky = true;
} break;
case RS::ENV_BG_CANVAS: {
- if (rb.is_valid()) {
+ if (!is_reflection_probe) {
RID texture = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(rb->get_render_target());
copy_effects->copy_to_fb_rect(texture, color_only_framebuffer, Rect2i(), false, false, false, false, RID(), false, false, true);
}
@@ -1812,7 +1810,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Setup Sky");
// Setup our sky render information for this frame/viewport
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
Vector3 eye_offset;
Projection correction;
correction.set_depth_correction(true);
@@ -1849,7 +1847,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid();
- bool using_ssao = depth_pre_pass && rb.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment);
+ bool using_ssao = depth_pre_pass && !is_reflection_probe && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment);
bool continue_depth = false;
if (depth_pre_pass) { //depth pre pass
@@ -1881,7 +1879,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi);
}
- if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)");
RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)");
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) {
@@ -1915,7 +1913,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
p_render_data->scene_data->opaque_prepass_threshold = 0.0f;
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, rb.is_valid());
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true);
RENDER_TIMESTAMP("Render Opaque Pass");
@@ -1996,7 +1994,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_end_label();
}
- if (rb.is_valid() && !can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ if (!can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
// Handle views individual, might want to look at rewriting our resolve to do both layers in one pass.
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v));
@@ -2008,7 +2006,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
}
- if (rb.is_valid() && !can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ if (!can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]);
}
@@ -2054,7 +2052,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true);
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
{
uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
@@ -2415,8 +2413,7 @@ void RenderForwardClustered::_render_shadow_process() {
void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
RD::get_singleton()->draw_command_begin_label("Shadow Render");
- for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
- SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
+ for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) {
RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -3376,9 +3373,7 @@ int RenderForwardClustered::sdfgi_get_pending_region_count(const Ref<RenderScene
Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
int dirty_count = 0;
- for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
- const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i];
-
+ for (const RendererRD::GI::SDFGI::Cascade &c : sdfgi->cascades) {
if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) {
dirty_count++;
} else {
@@ -3771,6 +3766,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D
case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata)->data->dirty_dependencies = true;
} break;
case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
@@ -3785,6 +3781,7 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::D
}
void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata)->data->dirty_dependencies = true;
}
RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
@@ -4007,11 +4004,11 @@ RenderForwardClustered::~RenderForwardClustered() {
RSG::light_storage->directional_shadow_atlas_set_size(0);
{
- for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) {
- RD::get_singleton()->free(scene_state.uniform_buffers[i]);
+ for (const RID &rid : scene_state.uniform_buffers) {
+ RD::get_singleton()->free(rid);
}
- for (uint32_t i = 0; i < scene_state.implementation_uniform_buffers.size(); i++) {
- RD::get_singleton()->free(scene_state.implementation_uniform_buffers[i]);
+ for (const RID &rid : scene_state.implementation_uniform_buffers) {
+ RD::get_singleton()->free(rid);
}
RD::get_singleton()->free(scene_state.lightmap_buffer);
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
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 7eabce2f79..2aaea4288b 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
@@ -44,7 +44,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
valid = false;
ubo_size = 0;
uniforms.clear();
- uses_screen_texture = false;
if (code.is_empty()) {
return; //just invalid, but no error
@@ -73,9 +72,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
uses_position = false;
uses_sss = false;
uses_transmittance = false;
- uses_screen_texture = false;
- uses_depth_texture = false;
- uses_normal_texture = false;
uses_time = false;
writes_modelview_or_projection = false;
uses_world_coordinates = false;
@@ -120,9 +116,6 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
- actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
- actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
- actions.usage_flag_pointers["NORMAL_ROUGHNESS_TEXTURE"] = &uses_normal_texture;
actions.usage_flag_pointers["DISCARD"] = &uses_discard;
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
@@ -151,6 +144,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+ 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_vertex_time = gen_code.uses_vertex_time;
uses_fragment_time = gen_code.uses_fragment_time;
@@ -607,9 +603,6 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.renames["POINT_COORD"] = "gl_PointCoord";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
actions.renames["SCREEN_UV"] = "screen_uv";
- actions.renames["SCREEN_TEXTURE"] = "color_buffer";
- actions.renames["DEPTH_TEXTURE"] = "depth_buffer";
- actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
actions.renames["FOG"] = "fog";
@@ -674,7 +667,6 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
- actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
@@ -707,10 +699,6 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
- actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps
- actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]";
- actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter
-
actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
@@ -729,6 +717,8 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs";
+ actions.check_multiview_samplers = true; // make sure we check sampling multiview textures
+
compiler.initialize(actions);
}
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 78d29e2a41..7d9ca070b0 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -251,7 +251,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
Size2i target_size = render_buffers->get_target_size();
Size2i internal_size = render_buffers->get_internal_size();
- // can't do our blit pass if resolutions don't match
+ // can't do our blit pass if resolutions don't match, this should already have been checked.
ERR_FAIL_COND_V(target_size != internal_size, RID());
// - opaque pass
@@ -579,8 +579,8 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
}
//cube shadows are rendered in their own way
- for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) {
- _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info);
+ 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);
}
if (p_render_data->directional_shadows.size()) {
@@ -632,7 +632,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
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.affine_inverse());
+ 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;
}
@@ -640,16 +640,18 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- Ref<RenderSceneBuffersRD> rb;
+ ERR_FAIL_NULL(p_render_data);
+
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
+
Ref<RenderBufferDataForwardMobile> rb_data;
- if (p_render_data->render_buffers.is_valid()) {
- rb = p_render_data->render_buffers;
- if (rb->has_custom_data(RB_SCOPE_MOBILE)) {
- // Our forward mobile custom data buffer will only be available when we're rendering our normal view.
- // This will not be available when rendering reflection probes.
- rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
- }
+ if (rb->has_custom_data(RB_SCOPE_MOBILE)) {
+ // Our forward mobile custom data buffer will only be available when we're rendering our normal view.
+ // This will not be available when rendering reflection probes.
+ rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
}
+ bool is_reflection_probe = p_render_data->reflection_probe.is_valid();
RENDER_TIMESTAMP("Prepare 3D Scene");
@@ -697,7 +699,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
}
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
@@ -715,20 +717,26 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// setup rendering to render buffer
screen_size = p_render_data->render_buffers->get_internal_size();
- if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
- // can't do blit subpass
+ if (rb->get_scaling_3d_mode() != RS::VIEWPORT_SCALING_3D_MODE_OFF) {
+ // can't do blit subpass because we're scaling
using_subpass_post_process = false;
} else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
- // can't do blit subpass
+ // can't do blit subpass because we're using post processes
using_subpass_post_process = false;
}
if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
- // can't use our last two subpasses
+ // can't use our last two subpasses because we're reading from screen texture or depth texture
using_subpass_transparent = false;
using_subpass_post_process = false;
}
+ // We do this last because our get_color_fbs creates and caches the framebuffer if we need it.
+ if (using_subpass_post_process && rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
+ // can't do blit subpass because we don't have all subpasses
+ using_subpass_post_process = false;
+ }
+
if (using_subpass_post_process) {
// all as subpasses
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);
@@ -748,7 +756,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Render Setup");
_setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform);
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
@@ -826,7 +834,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Setup Sky");
// Setup our sky render information for this frame/viewport
- if (p_render_data->reflection_probe.is_valid()) {
+ if (is_reflection_probe) {
Vector3 eye_offset;
Projection correction;
correction.set_depth_correction(true);
@@ -890,7 +898,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
+ _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, p_render_data->render_buffers.is_valid());
if (using_subpass_transparent && using_subpass_post_process) {
RENDER_TIMESTAMP("Render Opaque + Transparent + Tonemap");
@@ -1019,7 +1027,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
- // _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
+ // _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false);
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
@@ -1059,9 +1067,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
_disable_clear_request(p_render_data);
}
- if (rb.is_valid()) {
- _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex);
- }
+ _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex);
}
/* these are being called from RendererSceneRenderRD::_pre_opaque_render */
@@ -1334,8 +1340,7 @@ void RenderForwardMobile::_render_shadow_process() {
void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
RD::get_singleton()->draw_command_begin_label("Shadow Render");
- for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
- SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
+ for (SceneState::ShadowPass &shadow_pass : scene_state.shadow_passes) {
RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1919,7 +1924,6 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) {
- Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers;
RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID();
RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID();
@@ -2232,6 +2236,9 @@ RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base
ginstance->data->base = p_base;
ginstance->data->base_type = type;
+ ginstance->data->dependency_tracker.userdata = ginstance;
+ ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
+ ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
ginstance->_mark_dirty();
@@ -2668,6 +2675,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe
case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata)->data->dirty_dependencies = true;
} break;
case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
@@ -2682,6 +2690,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::Depe
}
void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
+ static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata)->data->dirty_dependencies = true;
}
/* misc */
@@ -2804,8 +2813,8 @@ RenderForwardMobile::~RenderForwardMobile() {
}
{
- for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) {
- RD::get_singleton()->free(scene_state.uniform_buffers[i]);
+ for (const RID &rid : scene_state.uniform_buffers) {
+ RD::get_singleton()->free(rid);
}
RD::get_singleton()->free(scene_state.lightmap_buffer);
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
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 ee4c8001eb..f9eecf4dc7 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
@@ -46,7 +46,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
valid = false;
ubo_size = 0;
uniforms.clear();
- uses_screen_texture = false;
if (code.is_empty()) {
return; //just invalid, but no error
@@ -74,9 +73,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
uses_vertex = false;
uses_sss = false;
uses_transmittance = false;
- uses_screen_texture = false;
- uses_depth_texture = false;
- uses_normal_texture = false;
uses_time = false;
writes_modelview_or_projection = false;
uses_world_coordinates = false;
@@ -121,9 +117,6 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
// actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
// actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
- actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
- actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
- actions.usage_flag_pointers["NORMAL_ROUGHNESS_TEXTURE"] = &uses_normal_texture;
actions.usage_flag_pointers["DISCARD"] = &uses_discard;
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
@@ -152,6 +145,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
depth_test = DepthTest(depth_testi);
uses_vertex_time = gen_code.uses_vertex_time;
uses_fragment_time = gen_code.uses_fragment_time;
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+ 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;
#if 0
print_line("**compiling shader:");
@@ -498,9 +495,6 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.renames["POINT_COORD"] = "gl_PointCoord";
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
actions.renames["SCREEN_UV"] = "screen_uv";
- actions.renames["SCREEN_TEXTURE"] = "color_buffer";
- actions.renames["DEPTH_TEXTURE"] = "depth_buffer";
- actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
actions.renames["FOG"] = "fog";
@@ -565,7 +559,6 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
- actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
@@ -616,6 +609,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
+ actions.check_multiview_samplers = true; // make sure we check sampling multiview textures
compiler.initialize(actions);
}
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 1f92697ecc..6f1f00cedc 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
@@ -128,6 +128,7 @@ public:
bool uses_screen_texture = false;
bool uses_depth_texture = false;
bool uses_normal_texture = false;
+ bool uses_screen_texture_mipmaps = false;
bool uses_time = false;
bool uses_vertex_time = false;
bool uses_fragment_time = false;
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 0c6dcb553a..bd8c11186e 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -455,7 +455,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
light_count++;
- if (light_count == MAX_LIGHTS_PER_ITEM) {
+ if (light_count == MAX_LIGHTS_PER_ITEM - 1) {
break;
}
}
@@ -525,10 +525,12 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
if (rect->flags & CANVAS_RECT_FLIP_H) {
src_rect.size.x *= -1;
+ push_constant.flags |= FLAGS_FLIP_H;
}
if (rect->flags & CANVAS_RECT_FLIP_V) {
src_rect.size.y *= -1;
+ push_constant.flags |= FLAGS_FLIP_V;
}
if (rect->flags & CANVAS_RECT_TRANSPOSE) {
@@ -1429,6 +1431,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c);
if (cm->mesh_instance.is_valid()) {
mesh_storage->mesh_instance_check_for_update(cm->mesh_instance);
+ mesh_storage->mesh_instance_set_canvas_item_transform(cm->mesh_instance, canvas_transform_inverse * ci->final_transform);
update_skeletons = true;
}
}
@@ -1547,6 +1550,9 @@ void RendererCanvasRenderRD::light_set_texture(RID p_rid, RID p_texture) {
if (cl->texture == p_texture) {
return;
}
+
+ ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture));
+
if (cl->texture.is_valid()) {
texture_storage->texture_remove_from_decal_atlas(cl->texture);
}
@@ -2034,7 +2040,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PMALPHA);
actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_mode, BLEND_MODE_DISABLED);
- actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
actions.usage_flag_pointers["texture_sdf"] = &uses_sdf;
actions.usage_flag_pointers["TIME"] = &uses_time;
@@ -2046,6 +2051,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+ uses_screen_texture = gen_code.uses_screen_texture;
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
@@ -2423,7 +2429,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture";
actions.renames["SPECULAR_SHININESS"] = "specular_shininess";
actions.renames["SCREEN_UV"] = "screen_uv";
- actions.renames["SCREEN_TEXTURE"] = "screen_texture";
actions.renames["SCREEN_PIXEL_SIZE"] = "canvas_data.screen_pixel_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
actions.renames["POINT_COORD"] = "gl_PointCoord";
@@ -2444,7 +2449,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
actions.renames["screen_uv_to_sdf"] = "screen_uv_to_sdf";
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
- actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV";
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
@@ -2459,7 +2463,6 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
actions.custom_samplers["TEXTURE"] = "texture_sampler";
actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler";
actions.custom_samplers["SPECULAR_SHININESS_TEXTURE"] = "texture_sampler";
- actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; //mipmap and filter for screen texture
actions.sampler_array_name = "material_samplers";
actions.base_texture_binding_index = 1;
actions.texture_layout_set = MATERIAL_UNIFORM_SET;
@@ -2632,8 +2635,10 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() {
shader_type canvas_item;
+uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
+
void fragment() {
- vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
+ vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0);
if (c.a > 0.0001) {
c.rgb /= c.a;
@@ -2657,8 +2662,10 @@ void fragment() {
shader_type canvas_item;
+uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
+
void fragment() {
- vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
+ vec4 c = textureLod(screen_texture, SCREEN_UV, 0.0);
COLOR.rgb = c.rgb;
}
)");
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 266083fc49..7dea4a1a65 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -86,6 +86,9 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
FLAGS_USE_MSDF = (1 << 28),
FLAGS_USE_LCD = (1 << 29),
+
+ FLAGS_FLIP_H = (1 << 30),
+ FLAGS_FLIP_V = (1 << 31),
};
enum {
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index 1d45db8eaf..885ea18151 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -253,6 +253,11 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());
+ if (!rb->has_internal_texture()) {
+ // We're likely rendering reflection probes where we can't use our backbuffers.
+ return;
+ }
+
RD::get_singleton()->draw_command_begin_label("Copy screen texture");
rb->allocate_blur_textures();
@@ -292,6 +297,11 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());
+ if (!rb->has_depth_texture()) {
+ // We're likely rendering reflection probes where we can't use our backbuffers.
+ return;
+ }
+
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
// note, this only creates our back depth texture if we haven't already created it.
@@ -321,9 +331,13 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ ERR_FAIL_NULL(p_render_data);
+
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
ERR_FAIL_COND(rb.is_null());
+ ERR_FAIL_COND_MSG(p_render_data->reflection_probe.is_valid(), "Post processes should not be applied on reflection probes.");
+
// Glow, auto exposure and DoF (if enabled).
Size2i internal_size = rb->get_internal_size();
@@ -539,7 +553,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
tonemap.view_count = rb->get_view_count();
RID dest_fb;
- if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) {
+ if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
// If we use FSR to upscale we need to write our result into an intermediate buffer.
// Note that this is cached so we only create the texture the first time.
RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
@@ -556,10 +570,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RD::get_singleton()->draw_command_end_label();
}
- if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) {
- // TODO Investigate? Does this work? We never write into our render target and we've already done so up above in our tonemapper.
- // I think FSR should either work before our tonemapper or as an alternative of our tonemapper.
-
+ if (fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale");
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
@@ -921,11 +932,9 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
// getting this here now so we can direct call a bunch of things more easily
- Ref<RenderSceneBuffersRD> rb;
- if (p_render_buffers.is_valid()) {
- rb = p_render_buffers; // cast it...
- ERR_FAIL_COND(rb.is_null());
- }
+ ERR_FAIL_COND(p_render_buffers.is_null());
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND(rb.is_null());
// setup scene data
RenderSceneDataRD scene_data;
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 2d5263a3e2..533a912a34 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -165,8 +165,7 @@ void ShaderRD::_clear_version(Version *p_version) {
}
void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, const Version *p_version, const StageTemplate &p_template) {
- for (uint32_t i = 0; i < p_template.chunks.size(); i++) {
- const StageTemplate::Chunk &chunk = p_template.chunks[i];
+ for (const StageTemplate::Chunk &chunk : p_template.chunks) {
switch (chunk.type) {
case StageTemplate::Chunk::TYPE_VERSION_DEFINES: {
builder.append("\n"); //make sure defines begin at newline
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index eb5f68849e..1fb8b28b15 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -502,6 +502,12 @@ void main() {
if (normal_used || (using_light && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0);
+ if (bool(draw_data.flags & FLAGS_FLIP_H)) {
+ normal.x = -normal.x;
+ }
+ if (bool(draw_data.flags & FLAGS_FLIP_V)) {
+ normal.y = -normal.y;
+ }
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
normal_used = true;
} else {
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 1b627a3e81..a904f4e0a6 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -27,6 +27,9 @@
#define FLAGS_USE_MSDF (1 << 28)
#define FLAGS_USE_LCD (1 << 29)
+#define FLAGS_FLIP_H (1 << 30)
+#define FLAGS_FLIP_V (1 << 31)
+
#define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1
#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
@@ -134,7 +137,7 @@ layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture;
layout(set = 0, binding = 5) uniform sampler shadow_sampler;
-layout(set = 0, binding = 6) uniform texture2D screen_texture;
+layout(set = 0, binding = 6) uniform texture2D color_buffer;
layout(set = 0, binding = 7) uniform texture2D sdf_texture;
layout(set = 0, binding = 8) uniform sampler material_samplers[12];
diff --git a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
index 134aae5ce7..b1ff46dd3b 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
@@ -56,7 +56,7 @@ vec4 screen_space_to_view_space_depth(vec4 p_depth) {
float depth_linearize_mul = params.z_near;
float depth_linearize_add = params.z_far;
- // Optimised version of "-cameraClipNear / (cameraClipFar - projDepth * (cameraClipFar - cameraClipNear)) * cameraClipFar"
+ // Optimized version of "-cameraClipNear / (cameraClipFar - projDepth * (cameraClipFar - cameraClipNear)) * cameraClipFar"
// Set your depth_linearize_mul and depth_linearize_add to:
// depth_linearize_mul = ( cameraClipFar * cameraClipNear) / ( cameraClipFar - cameraClipNear );
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
index 2a87e273bc..ffaa6872c9 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
@@ -221,7 +221,7 @@ void SSAOTap(const int p_quality_level, inout float r_obscurance_sum, inout floa
// snap to pixel center (more correct obscurance math, avoids artifacts)
sample_offset = round(sample_offset);
- // calculate MIP based on the sample distance from the centre, similar to as described
+ // calculate MIP based on the sample distance from the center, similar to as described
// in http://graphics.cs.williams.edu/papers/SAOHPG12/.
float mip_level = (p_quality_level < SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset);
@@ -259,7 +259,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
// get this pixel's viewspace depth
pix_z = valuesUL.y;
- // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0)
+ // get left right top bottom neighboring pixels for edge detection (gets compiled out on quality_level == 0)
pix_left_z = valuesUL.x;
pix_top_z = valuesUL.z;
pix_right_z = valuesBR.z;
@@ -304,7 +304,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
float obscurance_sum = 0.0;
float weight_sum = 0.0;
- // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
+ // edge mask for between this and left/right/top/bottom neighbor pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0);
// Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats
@@ -318,7 +318,7 @@ void generate_SSAO_shadows_internal(out float r_shadow_term, out vec4 r_edges, o
if (!p_adaptive_base && (p_quality_level >= SSAO_DETAIL_AO_ENABLE_AT_QUALITY_PRESET)) {
// disable in case of quality level 4 (reference)
if (p_quality_level != 4) {
- //approximate neighbouring pixels positions (actually just deltas or "positions - pix_center_pos" )
+ //approximate neighboring pixels positions (actually just deltas or "positions - pix_center_pos" )
vec3 normalized_viewspace_dir = vec3(pix_center_pos.xy / pix_center_pos.zz, 1.0);
vec3 pixel_left_delta = vec3(-pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_left_z - pix_center_pos.z);
vec3 pixel_right_delta = vec3(+pixel_size_at_center.x, 0.0, 0.0) + normalized_viewspace_dir * (pix_right_z - pix_center_pos.z);
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
index 04f98964e8..d234ab4417 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
@@ -80,7 +80,7 @@ void main() {
#ifdef PROCESS_MAPA
vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
@@ -98,7 +98,7 @@ void main() {
#ifdef PROCESS_MAPB
vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
index f6a9a92fac..45cc62d361 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
@@ -60,8 +60,8 @@ void main() {
int mx = int(pix_pos.x % 2);
int my = int(pix_pos.y % 2);
int index_center = mx + my * 2; // center index
- int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal
- int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical
+ int index_horizontal = (1 - mx) + my * 2; // neighboring, horizontal
+ int index_vertical = mx + (1 - my) * 2; // neighboring, vertical
int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal
vec2 center_val = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0).xy;
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
index 513791dfbf..de7b97953f 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
@@ -234,7 +234,7 @@ void SSILTap(const int p_quality_level, inout vec3 r_color_sum, inout float r_ob
// snap to pixel center (more correct obscurance math, avoids artifacts)
sample_offset = round(sample_offset);
- // calculate MIP based on the sample distance from the centre, similar to as described
+ // calculate MIP based on the sample distance from the center, similar to as described
// in http://graphics.cs.williams.edu/papers/SAOHPG12/.
float mip_level = (p_quality_level < SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET) ? (0) : (sample_pow_2_len + p_mip_offset);
@@ -272,7 +272,7 @@ void generate_SSIL(out vec3 r_color, out vec4 r_edges, out float r_obscurance, o
// get this pixel's viewspace depth
pix_z = valuesUL.y;
- // get left right top bottom neighbouring pixels for edge detection (gets compiled out on quality_level == 0)
+ // get left right top bottom neighboring pixels for edge detection (gets compiled out on quality_level == 0)
pix_left_z = valuesUL.x;
pix_top_z = valuesUL.z;
pix_right_z = valuesBR.z;
@@ -318,7 +318,7 @@ void generate_SSIL(out vec3 r_color, out vec4 r_edges, out float r_obscurance, o
float obscurance_sum = 0.0;
float weight_sum = 0.0;
- // edge mask for between this and left/right/top/bottom neighbour pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
+ // edge mask for between this and left/right/top/bottom neighbor pixels - not used in quality level 0 so initialize to "no edge" (1 is no edge, 0 is edge)
vec4 edgesLRTB = vec4(1.0, 1.0, 1.0, 1.0);
// Move center pixel slightly towards camera to avoid imprecision artifacts due to using of 16bit depth buffer; a lot smaller offsets needed when using 32bit floats
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
index 47c56571f6..f48e6c4341 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
@@ -124,14 +124,14 @@ void main() {
vec2 uv = (vec2(gl_GlobalInvocationID.xy) + vec2(0.5, 0.5)) * params.half_screen_pixel_size;
- vec4 centre = textureLod(source_ssil, uv, 0.0);
+ vec4 center = textureLod(source_ssil, uv, 0.0);
vec4 value = textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x * 3, -half_pixel.y)), 0.0) * 0.2;
value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x, -half_pixel.y * 3)), 0.0) * 0.2;
value += textureLod(source_ssil, vec2(uv + vec2(-half_pixel.x, +half_pixel.y * 3)), 0.0) * 0.2;
value += textureLod(source_ssil, vec2(uv + vec2(+half_pixel.x * 3, +half_pixel.y)), 0.0) * 0.2;
- vec4 sampled = value + centre * 0.2;
+ vec4 sampled = value + center * 0.2;
#else
#ifdef MODE_SMART
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
index 6b6b02739d..193e3458ab 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
@@ -82,7 +82,7 @@ void main() {
#ifdef PROCESS_MAPA
vec2 uv = (vec2(ssC) + 0.5) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
@@ -100,7 +100,7 @@ void main() {
#ifdef PROCESS_MAPB
vec2 uv = (vec2(ssC) + 0.5f) * params.half_screen_pixel_size * 2.0;
- float centre = textureLod(source_importance, uv, 0.0).x;
+ float center = textureLod(source_importance, uv, 0.0).x;
vec2 half_pixel = params.half_screen_pixel_size;
diff --git a/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
index 9e86ac0cf0..ed85b8ee4c 100644
--- a/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
@@ -62,8 +62,8 @@ void main() {
int mx = int(pix_pos.x % 2);
int my = int(pix_pos.y % 2);
int index_center = mx + my * 2; // center index
- int index_horizontal = (1 - mx) + my * 2; // neighbouring, horizontal
- int index_vertical = mx + (1 - my) * 2; // neighbouring, vertical
+ int index_horizontal = (1 - mx) + my * 2; // neighboring, horizontal
+ int index_vertical = mx + (1 - my) * 2; // neighboring, vertical
int index_diagonal = (1 - mx) + (1 - my) * 2; // diagonal
vec4 color = texelFetch(source_texture, ivec3(pix_pos / uvec2(params.size_modifier), index_center), 0);
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
index 9f7449b8aa..06709f65d3 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
@@ -24,7 +24,7 @@ struct ProcessVoxel {
uint albedo; // rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors.
uint light; // rgbe8985 encoded total saved light, extra 2 bits for neighbors.
uint light_aniso; // 55555 light anisotropy, extra 2 bits for neighbors.
- //total neighbours: 26
+ //total neighbors: 26
};
#ifdef MODE_PROCESS_STATIC
@@ -443,10 +443,10 @@ void main() {
imageStore(dst_aniso1, positioni, vec4(aniso1, 0.0, 0.0));
imageStore(dst_light, positioni, uvec4(light_total_rgbe));
- //also fill neighbours, so light interpolation during the indirect pass works
+ //also fill neighbors, so light interpolation during the indirect pass works
- //recover the neighbour list from the leftover bits
- uint neighbours = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24);
+ //recover the neighbor list from the leftover bits
+ uint neighbors = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24);
const uint max_neighbours = 26;
const ivec3 neighbour_positions[max_neighbours] = ivec3[](
@@ -478,7 +478,7 @@ void main() {
ivec3(1, 1, 1));
for (uint i = 0; i < max_neighbours; i++) {
- if (bool(neighbours & (1 << i))) {
+ if (bool(neighbors & (1 << i))) {
ivec3 neighbour_pos = positioni + neighbour_positions[i];
imageStore(dst_light, neighbour_pos, uvec4(light_total_rgbe));
imageStore(dst_aniso0, neighbour_pos, aniso0);
diff --git a/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
index bce98f4054..dd35ae3b73 100644
--- a/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
@@ -102,10 +102,10 @@ dispatch_data;
struct ProcessVoxel {
uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
- uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours
- uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
- uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
- //total neighbours: 26
+ uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors
+ uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbors
+ uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbors
+ //total neighbors: 26
};
layout(set = 0, binding = 11, std430) restrict buffer writeonly ProcessVoxels {
@@ -135,10 +135,10 @@ dispatch_data;
struct ProcessVoxel {
uint position; // xyz 7 bit packed, extra 11 bits for neighbors.
- uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbours
- uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbours
- uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours
- //total neighbours: 26
+ uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neighbors
+ uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbors
+ uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbors
+ //total neighbors: 26
};
layout(set = 0, binding = 6, std430) restrict buffer readonly ProcessVoxels {
@@ -1016,14 +1016,14 @@ void main() {
store_positions[index].albedo = rgb >> 1; //store as it comes (555) to avoid precision loss (and move away the alpha bit)
store_positions[index].albedo |= (facing & 0x3F) << 15; // store facing in bits 15-21
- store_positions[index].albedo |= neighbour_bits << 21; //store lower 11 bits of neighbours with remaining albedo
- store_positions[index].position |= (neighbour_bits >> 11) << 21; //store 11 bits more of neighbours with position
+ store_positions[index].albedo |= neighbour_bits << 21; //store lower 11 bits of neighbors with remaining albedo
+ store_positions[index].position |= (neighbour_bits >> 11) << 21; //store 11 bits more of neighbors with position
store_positions[index].light = imageLoad(src_light, pos).r;
store_positions[index].light_aniso = imageLoad(src_light_aniso, pos).r;
- //add neighbours
- store_positions[index].light |= (neighbour_bits >> 22) << 30; //store 2 bits more of neighbours with light
- store_positions[index].light_aniso |= (neighbour_bits >> 24) << 30; //store 2 bits more of neighbours with aniso
+ //add neighbors
+ store_positions[index].light |= (neighbour_bits >> 22) << 30; //store 2 bits more of neighbors with light
+ store_positions[index].light_aniso |= (neighbour_bits >> 24) << 30; //store 2 bits more of neighbors with aniso
}
groupMemoryBarrier();
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 d32e6d717f..c6a3c42e57 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
@@ -118,13 +118,13 @@ layout(location = 10) out flat uint instance_index_interp;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-vec3 normal_roughness_uv(vec2 uv) {
+vec3 multiview_uv(vec2 uv) {
return vec3(uv, ViewIndex);
}
#else // USE_MULTIVIEW
// Set to zero, not supported in non stereo
#define ViewIndex 0
-vec2 normal_roughness_uv(vec2 uv) {
+vec2 multiview_uv(vec2 uv) {
return uv;
}
#endif //USE_MULTIVIEW
@@ -550,13 +550,13 @@ layout(location = 10) in flat uint instance_index_interp;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif // has_VK_KHR_multiview
-vec3 normal_roughness_uv(vec2 uv) {
+vec3 multiview_uv(vec2 uv) {
return vec3(uv, ViewIndex);
}
#else // USE_MULTIVIEW
// Set to zero, not supported in non stereo
#define ViewIndex 0
-vec2 normal_roughness_uv(vec2 uv) {
+vec2 multiview_uv(vec2 uv) {
return uv;
}
#endif //USE_MULTIVIEW
@@ -1305,24 +1305,26 @@ void fragment_shader(in SceneData scene_data) {
}
if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
-
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- vec3 ref_vec = normalize(reflect(-view, normal));
- ref_vec = mix(ref_vec, normal, roughness * roughness);
+ // Make vertex orientation the world one, but still align to camera.
+ vec3 cam_pos = mat3(scene_data.inv_view_matrix) * vertex;
+ vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normal;
+ vec3 ref_vec = mat3(scene_data.inv_view_matrix) * normalize(reflect(-view, normal));
+
//find arbitrary tangent and bitangent, then build a matrix
- vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
- vec3 tangent = normalize(cross(v0, normal));
- vec3 bitangent = normalize(cross(tangent, normal));
- mat3 normal_mat = mat3(tangent, bitangent, normal);
+ vec3 v0 = abs(cam_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
+ vec3 tangent = normalize(cross(v0, cam_normal));
+ vec3 bitangent = normalize(cross(tangent, cam_normal));
+ mat3 normal_mat = mat3(tangent, bitangent, cam_normal);
vec4 amb_accum = vec4(0.0);
vec4 spec_accum = vec4(0.0);
- voxel_gi_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ voxel_gi_compute(index1, cam_pos, cam_normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
uint index2 = instances.data[instance_index].gi_offset >> 16;
if (index2 != 0xFFFF) {
- voxel_gi_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
+ voxel_gi_compute(index2, cam_pos, cam_normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum);
}
if (amb_accum.a > 0.0) {
@@ -1351,8 +1353,8 @@ void fragment_shader(in SceneData scene_data) {
#endif // USE_MULTIVIEW
for (int i = 0; i < 4; i++) {
- const vec2 neighbours[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
- vec2 neighbour_coord = base_coord + neighbours[i] * scene_data.screen_pixel_size;
+ const vec2 neighbors[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
+ vec2 neighbour_coord = base_coord + neighbors[i] * scene_data.screen_pixel_size;
#ifdef USE_MULTIVIEW
float neighbour_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0);
#else // USE_MULTIVIEW
@@ -1798,7 +1800,7 @@ void fragment_shader(in SceneData scene_data) {
shadow = float(shadow1 >> ((i - 4u) * 8u) & 0xFFu) / 255.0;
}
- shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity;
+ shadow = mix(1.0, shadow, directional_lights.data[i].shadow_opacity);
#endif
blur_shadow(shadow);
@@ -2082,7 +2084,7 @@ void fragment_shader(in SceneData scene_data) {
float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
- //store as 8985 to have 2 extra neighbour bits
+ //store as 8985 to have 2 extra neighbor bits
uint light_rgbe = ((uint(sRed) & 0x1FFu) >> 1) | ((uint(sGreen) & 0x1FFu) << 8) | (((uint(sBlue) & 0x1FFu) >> 1) << 17) | ((uint(exps) & 0x1Fu) << 25);
imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
index 1f524313f2..8ff7a784dc 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
@@ -271,15 +271,16 @@ layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid;
#define multiviewSampler sampler2D
#else
-layout(set = 1, binding = 10) uniform texture2D depth_buffer;
-layout(set = 1, binding = 11) uniform texture2D color_buffer;
-
#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 10) uniform texture2DArray depth_buffer;
+layout(set = 1, binding = 11) uniform texture2DArray color_buffer;
layout(set = 1, binding = 12) uniform texture2DArray normal_roughness_buffer;
layout(set = 1, binding = 14) uniform texture2DArray ambient_buffer;
layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer;
#define multiviewSampler sampler2DArray
#else // USE_MULTIVIEW
+layout(set = 1, binding = 10) uniform texture2D depth_buffer;
+layout(set = 1, binding = 11) uniform texture2D color_buffer;
layout(set = 1, binding = 12) uniform texture2D normal_roughness_buffer;
layout(set = 1, binding = 14) uniform texture2D ambient_buffer;
layout(set = 1, binding = 15) uniform texture2D reflection_buffer;
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 5e64d4e651..90e902ca33 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
@@ -112,9 +112,15 @@ layout(location = 9) out highp float dp_clip;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif
+vec3 multiview_uv(vec2 uv) {
+ return vec3(uv, ViewIndex);
+}
#else
// Set to zero, not supported in non stereo
#define ViewIndex 0
+vec2 multiview_uv(vec2 uv) {
+ return uv;
+}
#endif //USE_MULTIVIEW
invariant gl_Position;
@@ -523,9 +529,15 @@ layout(location = 9) highp in float dp_clip;
// !BAS! This needs to become an input once we implement our fallback!
#define ViewIndex 0
#endif
+vec3 multiview_uv(vec2 uv) {
+ return vec3(uv, ViewIndex);
+}
#else
// Set to zero, not supported in non stereo
#define ViewIndex 0
+vec2 multiview_uv(vec2 uv) {
+ return uv;
+}
#endif //USE_MULTIVIEW
//defines to keep compatibility with vertex
@@ -1515,6 +1527,8 @@ void main() {
} else {
shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
}
+
+ shadow = mix(1.0, shadow, directional_lights.data[i].shadow_opacity);
#endif
blur_shadow(shadow);
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
index 631ff0575b..78b39a356d 100644
--- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
@@ -154,8 +154,15 @@ layout(set = 1, binding = 5) uniform highp texture2D directional_shadow_atlas;
// this needs to change to providing just the lightmap we're using..
layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 9) uniform highp texture2DArray depth_buffer;
+layout(set = 1, binding = 10) uniform mediump texture2DArray color_buffer;
+#define multiviewSampler sampler2DArray
+#else
layout(set = 1, binding = 9) uniform highp texture2D depth_buffer;
layout(set = 1, binding = 10) uniform mediump texture2D color_buffer;
+#define multiviewSampler sampler2D
+#endif // USE_MULTIVIEW
/* Set 2 Skeleton & Instancing (can change per item) */
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index b30b0c8169..9dda62c28d 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -794,8 +794,13 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float light_length = length(light_rel_vec);
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
vec3 spot_dir = spot_lights.data[idx].direction;
- float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_lights.data[idx].cone_angle);
- float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_lights.data[idx].cone_angle));
+
+ // This conversion to a highp float is crucial to prevent light leaking
+ // due to precision errors in the following calculations (cone angle is mediump).
+ highp float cone_angle = spot_lights.data[idx].cone_angle;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
+ float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
+
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
float light_attenuation = spot_attenuation;
vec3 color = spot_lights.data[idx].color;
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index f5b233cca0..59c161548c 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -51,6 +51,15 @@ layout(push_constant, std430) uniform Params {
bool normalized_blend_shapes;
uint pad0;
uint pad1;
+
+ vec2 skeleton_transform_x;
+ vec2 skeleton_transform_y;
+
+ vec2 skeleton_transform_offset;
+ vec2 inverse_transform_x;
+
+ vec2 inverse_transform_y;
+ vec2 inverse_transform_offset;
}
params;
@@ -158,8 +167,12 @@ void main() {
m += mat4(bone_transforms.data[bones_23.x], bone_transforms.data[bones_23.x + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x;
m += mat4(bone_transforms.data[bones_23.y], bone_transforms.data[bones_23.y + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y;
- //reverse order because its transposed
- vertex = (vec4(vertex, 0.0, 1.0) * m).xy;
+ mat4 skeleton_matrix = mat4(vec4(params.skeleton_transform_x, 0.0, 0.0), vec4(params.skeleton_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(params.skeleton_transform_offset, 0.0, 1.0));
+ mat4 inverse_matrix = mat4(vec4(params.inverse_transform_x, 0.0, 0.0), vec4(params.inverse_transform_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(params.inverse_transform_offset, 0.0, 1.0));
+
+ m = skeleton_matrix * transpose(m) * inverse_matrix;
+
+ vertex = (m * vec4(vertex, 0.0, 1.0)).xy;
}
uint dst_offset = index * params.vertex_stride;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 673fc25595..f56cee9e12 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -232,6 +232,8 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) {
return;
}
+ ERR_FAIL_COND(p_texture.is_valid() && !texture_storage->owns_texture(p_texture));
+
if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
texture_storage->texture_remove_from_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
}
@@ -568,8 +570,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
r_directional_light_count = 0;
r_positional_light_count = 0;
- Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
-
omni_light_count = 0;
spot_light_count = 0;
@@ -720,7 +720,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
}
Transform3D light_transform = light_instance->transform;
- const real_t distance = camera_plane.distance_to(light_transform.origin);
+ const real_t distance = p_camera_transform.origin.distance_to(light_transform.origin);
if (light->distance_fade) {
const float fade_begin = light->distance_fade_begin;
@@ -745,7 +745,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
}
Transform3D light_transform = light_instance->transform;
- const real_t distance = camera_plane.distance_to(light_transform.origin);
+ const real_t distance = p_camera_transform.origin.distance_to(light_transform.origin);
if (light->distance_fade) {
const float fade_begin = light->distance_fade_begin;
@@ -787,6 +787,7 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
RS::LightType type = (i < omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
LightInstance *light_instance = (i < omni_light_count) ? omni_light_sort[index].light_instance : spot_light_sort[index].light_instance;
Light *light = (i < omni_light_count) ? omni_light_sort[index].light : spot_light_sort[index].light;
+ 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);
@@ -803,7 +804,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
float fade_begin = 0.0;
float fade_shadow = 0.0;
float fade_length = 0.0;
- real_t distance = 0.0;
float fade = 1.0;
float shadow_opacity_fade = 1.0;
@@ -811,7 +811,6 @@ void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const Paged
fade_begin = light->distance_fade_begin;
fade_shadow = light->distance_fade_shadow;
fade_length = light->distance_fade_length;
- distance = camera_plane.distance_to(light_transform.origin);
// Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
if (distance > fade_begin) {
@@ -1467,7 +1466,6 @@ bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_
fb.push_back(atlas->depth_buffer);
atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
- atlas->render_buffers->cleanup();
atlas->render_buffers->configure_for_reflections(Size2i(atlas->size, atlas->size));
}
@@ -1556,6 +1554,11 @@ bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
if (rpi->processing_side == 6) {
rpi->processing_side = 0;
rpi->processing_layer++;
+ if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) {
+ rpi->rendering = false;
+ rpi->processing_layer = 1;
+ return true;
+ }
}
return false;
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index f7c8b8833b..d359219128 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -226,7 +226,7 @@ private:
Color ambient_color;
float ambient_color_energy = 1.0;
float max_distance = 0;
- Vector3 extents = Vector3(1, 1, 1);
+ Vector3 extents = Vector3(10, 10, 10);
Vector3 origin_offset;
bool interior = false;
bool box_projection = false;
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 66ae1e8d1a..d631a89dd2 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -2685,6 +2685,14 @@ void MaterialStorage::material_free(RID p_rid) {
Material *material = material_owner.get_or_null(p_rid);
ERR_FAIL_COND(!material);
+ // Need to clear texture arrays to prevent spin locking of their RID's.
+ // This happens when the app is being closed.
+ for (KeyValue<StringName, Variant> &E : material->params) {
+ if (E.value.get_type() == Variant::ARRAY) {
+ Array(E.value).clear();
+ }
+ }
+
material_set_shader(p_rid, RID()); //clean up shader
material->dependency.deleted_notify(p_rid);
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 62da62403f..9124886764 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -842,15 +842,15 @@ void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int
}
void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
- for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
- if (mi->surfaces[i].versions) {
- for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
- RD::get_singleton()->free(mi->surfaces[i].versions[j].vertex_array);
+ for (const RendererRD::MeshStorage::MeshInstance::Surface &surface : mi->surfaces) {
+ if (surface.versions) {
+ for (uint32_t j = 0; j < surface.version_count; j++) {
+ RD::get_singleton()->free(surface.versions[j].vertex_array);
}
- memfree(mi->surfaces[i].versions);
+ memfree(surface.versions);
}
- if (mi->surfaces[i].vertex_buffer.is_valid()) {
- RD::get_singleton()->free(mi->surfaces[i].vertex_buffer);
+ if (surface.vertex_buffer.is_valid()) {
+ RD::get_singleton()->free(surface.vertex_buffer);
}
}
mi->surfaces.clear();
@@ -866,8 +866,8 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
if (mesh->blend_shape_count > 0 && mi->blend_weights_buffer.is_null()) {
mi->blend_weights.resize(mesh->blend_shape_count);
- for (uint32_t i = 0; i < mi->blend_weights.size(); i++) {
- mi->blend_weights[i] = 0;
+ for (float &weight : mi->blend_weights) {
+ weight = 0;
}
mi->blend_weights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * mi->blend_weights.size(), mi->blend_weights.to_byte_array());
mi->weights_dirty = true;
@@ -930,6 +930,11 @@ void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
}
}
+void MeshStorage::mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) {
+ MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
+ mi->canvas_item_transform_2d = p_transform;
+}
+
void MeshStorage::update_mesh_instances() {
while (dirty_mesh_instance_weights.first()) {
MeshInstance *mi = dirty_mesh_instance_weights.first()->self();
@@ -981,6 +986,22 @@ void MeshStorage::update_mesh_instances() {
push_constant.skin_stride = (mi->mesh->surfaces[i]->skin_buffer_size / mi->mesh->surfaces[i]->vertex_count) / 4;
push_constant.skin_weight_offset = (mi->mesh->surfaces[i]->format & RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS) ? 4 : 2;
+ Transform2D transform = mi->canvas_item_transform_2d.affine_inverse() * sk->base_transform_2d;
+ push_constant.skeleton_transform_x[0] = transform.columns[0][0];
+ push_constant.skeleton_transform_x[1] = transform.columns[0][1];
+ push_constant.skeleton_transform_y[0] = transform.columns[1][0];
+ push_constant.skeleton_transform_y[1] = transform.columns[1][1];
+ push_constant.skeleton_transform_offset[0] = transform.columns[2][0];
+ push_constant.skeleton_transform_offset[1] = transform.columns[2][1];
+
+ Transform2D inverse_transform = transform.affine_inverse();
+ push_constant.inverse_transform_x[0] = inverse_transform.columns[0][0];
+ push_constant.inverse_transform_x[1] = inverse_transform.columns[0][1];
+ push_constant.inverse_transform_y[0] = inverse_transform.columns[1][0];
+ push_constant.inverse_transform_y[1] = inverse_transform.columns[1][1];
+ push_constant.inverse_transform_offset[0] = inverse_transform.columns[2][0];
+ push_constant.inverse_transform_offset[1] = inverse_transform.columns[2][1];
+
push_constant.blend_shape_count = mi->mesh->blend_shape_count;
push_constant.normalized_blend_shapes = mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED;
push_constant.pad0 = 0;
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index b62da5fd7b..c921523941 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -178,6 +178,7 @@ private:
bool weights_dirty = false;
SelfList<MeshInstance> weight_update_list;
SelfList<MeshInstance> array_update_list;
+ Transform2D canvas_item_transform_2d;
MeshInstance() :
weight_update_list(this), array_update_list(this) {}
};
@@ -256,6 +257,14 @@ private:
uint32_t normalized_blend_shapes;
uint32_t pad0;
uint32_t pad1;
+ float skeleton_transform_x[2];
+ float skeleton_transform_y[2];
+
+ float skeleton_transform_offset[2];
+ float inverse_transform_x[2];
+
+ float inverse_transform_y[2];
+ float inverse_transform_offset[2];
};
enum {
@@ -548,6 +557,7 @@ public:
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) override;
virtual void mesh_instance_check_for_update(RID p_mesh_instance) override;
+ virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) override;
virtual void update_mesh_instances() override;
/* MULTIMESH API */
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 6401d0f5d0..00fb8acca8 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -851,9 +851,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
collision_heightmap_texture = p_particles->sdf_collision_texture;
//replace in all other history frames where used because parameters are no longer valid if screen moves
- for (uint32_t i = 1; i < p_particles->frame_history.size(); i++) {
- if (p_particles->frame_history[i].collider_count > 0 && p_particles->frame_history[i].colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
- p_particles->frame_history[i].colliders[0] = frame_params.colliders[0];
+ for (ParticlesFrameParams &params : p_particles->frame_history) {
+ if (params.collider_count > 0 && params.colliders[0].type == ParticlesFrameParams::COLLISION_TYPE_2D_SDF) {
+ params.colliders[0] = frame_params.colliders[0];
}
}
}
@@ -1145,7 +1145,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
return;
}
- if (particles->particle_buffer.is_null()) {
+ if (particles->particle_buffer.is_null() || particles->trail_bind_pose_uniform_set.is_null()) {
return; //particles have not processed yet
}
@@ -1415,7 +1415,6 @@ void ParticlesStorage::update_particles() {
}
bool zero_time_scale = Engine::get_singleton()->get_time_scale() <= 0.0;
- bool updated = false;
if (particles->clear && particles->pre_process_time > 0.0) {
double frame_time;
@@ -1430,7 +1429,6 @@ void ParticlesStorage::update_particles() {
while (todo >= 0) {
_particles_process(particles, frame_time);
todo -= frame_time;
- updated = true;
}
}
@@ -1452,10 +1450,9 @@ void ParticlesStorage::update_particles() {
}
double todo = particles->frame_remainder + delta;
- while (todo >= frame_time || (particles->clear && !updated)) {
+ while (todo >= frame_time || particles->clear) {
_particles_process(particles, frame_time);
todo -= decr;
- updated = true;
}
particles->frame_remainder = todo;
@@ -1463,16 +1460,16 @@ void ParticlesStorage::update_particles() {
} else {
if (zero_time_scale) {
_particles_process(particles, 0.0);
- updated = true;
} else {
_particles_process(particles, RendererCompositorRD::singleton->get_frame_delta_time());
- updated = true;
}
}
- //copy particles to instance buffer
+ // Ensure that memory is initialized (the code above should ensure that _particles_process is always called at least once upon clearing).
+ DEV_ASSERT(!particles->clear);
- if (updated && particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
+ // Copy particles to instance buffer.
+ if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
//does not need view dependent operation, do copy here
ParticlesShader::CopyPushConstant copy_push_constant;
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
index d67a848a40..255719183f 100644
--- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
@@ -96,7 +96,7 @@ void RenderSceneBuffersRD::cleanup() {
named_textures.clear();
}
-void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
@@ -104,12 +104,7 @@ void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_interna
target_size = p_target_size;
internal_size = p_internal_size;
-
- // FIXME, right now we do this because only our clustered renderer supports FSR upscale
- // this does mean that with linear upscale if we use subpasses, we could get into trouble.
- if (!can_be_storage) {
- internal_size = target_size;
- }
+ scaling_3d_mode = p_scaling_3d_mode;
if (p_use_taa) {
// Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
@@ -193,6 +188,7 @@ void RenderSceneBuffersRD::configure_for_reflections(const Size2i p_reflection_s
target_size = p_reflection_size;
internal_size = p_reflection_size;
render_target = RID();
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
fsr_sharpness = 0.0;
msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
@@ -255,7 +251,7 @@ RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const Stri
}
RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) {
- // TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimisation.
+ // TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimization.
NTKey key(p_context, p_texture_name);
@@ -494,6 +490,16 @@ Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const String
// Depth texture
+bool RenderSceneBuffersRD::has_depth_texture() {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID depth = texture_storage->render_target_get_override_depth(render_target);
+ if (depth.is_valid()) {
+ return true;
+ } else {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
+ }
+}
+
RID RenderSceneBuffersRD::get_depth_texture() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RID depth = texture_storage->render_target_get_override_depth(render_target);
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 ff946f410f..50fb06c0d9 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
@@ -73,6 +73,7 @@ private:
// The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
Size2i internal_size = Size2i(0, 0);
+ RS::ViewportScaling3DMode scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
float fsr_sharpness = 0.2f;
// Aliassing settings
@@ -139,7 +140,7 @@ public:
void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
void cleanup();
- virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
void configure_for_reflections(const Size2i p_reflection_size);
virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
@@ -172,6 +173,7 @@ public:
_FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
_FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
_FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
+ _FORCE_INLINE_ RS::ViewportScaling3DMode get_scaling_3d_mode() const { return scaling_3d_mode; }
_FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
_FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
_FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }
@@ -183,6 +185,9 @@ public:
// For our internal textures we provide some easy access methods.
+ _FORCE_INLINE_ bool has_internal_texture() const {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
+ }
_FORCE_INLINE_ RID get_internal_texture() const {
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
}
@@ -190,6 +195,7 @@ public:
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
}
+ bool has_depth_texture();
RID get_depth_texture();
RID get_depth_texture(const uint32_t p_layer);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 06fda8fa9e..2eaa7824fb 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -422,8 +422,7 @@ TextureStorage::TextureStorage() {
tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
tformat.texture_type = RD::TEXTURE_TYPE_2D;
if (!RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) {
- tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
- tformat.format = RD::DATA_FORMAT_R8_UNORM;
+ tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
}
Vector<uint8_t> pv;
@@ -2206,6 +2205,12 @@ void TextureStorage::decal_instance_set_transform(RID p_decal_instance, const Tr
di->transform = p_transform;
}
+void TextureStorage::decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ ERR_FAIL_COND(!di);
+ di->sorting_offset = p_sorting_offset;
+}
+
/* DECAL DATA API */
void TextureStorage::free_decal_data() {
@@ -2233,7 +2238,7 @@ void TextureStorage::set_max_decals(const uint32_t p_max_decals) {
decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
}
-void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
+void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform) {
ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton();
Transform3D uv_xform;
@@ -2257,7 +2262,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
Transform3D xform = decal_instance->transform;
- real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+ real_t distance = p_camera_xform.origin.distance_to(xform.origin);
if (decal->distance_fade) {
float fade_begin = decal->distance_fade_begin;
@@ -2272,7 +2277,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
decal_sort[decal_count].decal_instance = decal_instance;
decal_sort[decal_count].decal = decal;
- decal_sort[decal_count].depth = distance;
+ decal_sort[decal_count].depth = distance - decal_instance->sorting_offset;
decal_count++;
}
@@ -2292,11 +2297,10 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
decal_instance->cull_mask = decal->cull_mask;
- Transform3D xform = decal_instance->transform;
float fade = 1.0;
if (decal->distance_fade) {
- const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+ const real_t distance = decal_sort[i].depth + decal_instance->sorting_offset;
const float fade_begin = decal->distance_fade_begin;
const float fade_length = decal->distance_fade_length;
@@ -2312,11 +2316,16 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
Transform3D scale_xform;
scale_xform.basis.scale(decal_extents);
- Transform3D to_decal_xform = (p_camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse();
+
+ Transform3D xform = decal_instance->transform;
+
+ Transform3D camera_inverse_xform = p_camera_xform.affine_inverse();
+
+ Transform3D to_decal_xform = (camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse();
MaterialStorage::store_transform(to_decal_xform, dd.xform);
Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized();
- normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
+ normal = camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
dd.normal[0] = normal.x;
dd.normal[1] = normal.y;
@@ -2350,7 +2359,7 @@ void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const
dd.normal_rect[2] = rect.size.x;
dd.normal_rect[3] = rect.size.y;
- Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
+ Basis normal_xform = camera_inverse_xform.basis * xform.basis.orthonormalized();
MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform);
} else {
dd.normal_rect[0] = 0;
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 1558342c3b..ea0df0b459 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -258,6 +258,7 @@ private:
struct DecalInstance {
RID decal;
Transform3D transform;
+ float sorting_offset = 0.0;
uint32_t cull_mask = 0;
RendererRD::ForwardID forward_id = -1;
};
@@ -646,6 +647,7 @@ public:
virtual RID decal_instance_create(RID p_decal) override;
virtual void decal_instance_free(RID p_decal_instance) override;
virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) override;
+ virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) override;
_FORCE_INLINE_ RID decal_instance_get_base(RID p_decal_instance) const {
DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
@@ -677,7 +679,7 @@ public:
void free_decal_data();
void set_max_decals(const uint32_t p_max_decals);
RID get_decal_buffer() { return decal_buffer; }
- void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
+ void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_xform);
/* RENDER TARGET API */
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
index d2f5e6f224..cabac4e9ee 100644
--- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
@@ -286,6 +286,10 @@ bool Utilities::has_os_feature(const String &p_feature) const {
return true;
}
+ if (p_feature == "astc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
return false;
}
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 2ea813aab0..6f4bb115fc 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -694,6 +694,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base_data = decal;
decal->instance = RSG::texture_storage->decal_instance_create(p_base);
+ RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);
} break;
case RS::INSTANCE_LIGHTMAP: {
InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
@@ -748,6 +749,10 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
+ if (instance->visible && RSG::light_storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) {
+ instance->scenario->dynamic_lights.erase(light->instance);
+ }
+
#ifdef DEBUG_ENABLED
if (light->geometries.size()) {
ERR_PRINT("BUG, indexing did not unpair geometries from light.");
@@ -867,6 +872,9 @@ void RendererSceneCull::instance_set_pivot_data(RID p_instance, float p_sorting_
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
ERR_FAIL_NULL(geom->geometry_instance);
geom->geometry_instance->set_pivot_data(p_sorting_offset, p_use_aabb_center);
+ } else if (instance->base_type == RS::INSTANCE_DECAL && instance->base_data) {
+ InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);
+ RSG::texture_storage->decal_instance_set_sorting_offset(decal->instance, instance->sorting_offset);
}
}
@@ -2820,7 +2828,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
ERR_FAIL_NULL(geom->geometry_instance);
+ cull_data.cull->lock.lock();
geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0);
+ cull_data.cull->lock.unlock();
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY);
}
@@ -2887,7 +2897,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
}
ERR_FAIL_NULL(geom->geometry_instance);
+ cull_data.cull->lock.lock();
geom->geometry_instance->set_lightmap_capture(sh);
+ cull_data.cull->lock.unlock();
idata.instance->last_frame_pass = frame_number;
}
@@ -2952,11 +2964,13 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
render_pass++;
scene_render->set_scene_pass(render_pass);
- if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
+ if (p_reflection_probe.is_null()) {
//no rendering code here, this is only to set up what needs to be done, request regions, etc.
scene_render->sdfgi_update(p_render_buffers, p_environment, p_camera_data->main_transform.origin); //update conditions for SDFGI (whether its used or not)
}
@@ -3038,7 +3052,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
{ //sdfgi
cull.sdfgi.region_count = 0;
- if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
+ if (p_reflection_probe.is_null()) {
cull.sdfgi.cascade_light_count = 0;
uint32_t prev_cascade = 0xFFFFFFFF;
@@ -3084,15 +3098,15 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
#endif
if (cull_to > thread_cull_threshold) {
//multiple threads
- for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
- scene_cull_result_threads[i].clear();
+ for (InstanceCullResult &thread : scene_cull_result_threads) {
+ thread.clear();
}
WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances"));
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
- for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
- scene_cull_result.append_from(scene_cull_result_threads[i]);
+ for (InstanceCullResult &thread : scene_cull_result_threads) {
+ scene_cull_result.append_from(thread);
}
} else {
@@ -3267,7 +3281,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
}
- if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
+ if (p_reflection_probe.is_null()) {
sdfgi_update_data.directional_lights = &directional_lights;
sdfgi_update_data.positional_light_instances = scenario->dynamic_lights.ptr();
sdfgi_update_data.positional_light_count = scenario->dynamic_lights.size();
@@ -4122,8 +4136,8 @@ RendererSceneCull::RendererSceneCull() {
scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count());
- for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
- scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
+ for (InstanceCullResult &thread : scene_cull_result_threads) {
+ thread.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
@@ -4151,8 +4165,8 @@ RendererSceneCull::~RendererSceneCull() {
}
scene_cull_result.reset();
- for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
- scene_cull_result_threads[i].reset();
+ for (InstanceCullResult &thread : scene_cull_result_threads) {
+ thread.reset();
}
scene_cull_result_threads.clear();
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index e2e6ea5aa2..a389e3e767 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -84,7 +84,7 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
Transform3D main_transform_inv = main_transform.inverse();
// 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
- Vector3 far_center = (planes[0][Projection::PLANE_FAR].center() + planes[1][Projection::PLANE_FAR].center()) * 0.5;
+ Vector3 far_center = (planes[0][Projection::PLANE_FAR].get_center() + planes[1][Projection::PLANE_FAR].get_center()) * 0.5;
Plane far(-z, far_center);
/////////////////////////////////////////////////////////////////////////////
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 05a3fccf1c..aecd0593bc 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -115,9 +115,8 @@ 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 scaling_3d_scale = p_viewport->scaling_3d_scale;
+ float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
- bool scaling_enabled = true;
if ((scaling_3d_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) && (scaling_3d_scale > 1.0)) {
// FSR is not designed for downsampling.
@@ -133,7 +132,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
}
if (scaling_3d_scale == 1.0) {
- scaling_enabled = false;
+ scaling_3d_mode = RS::VIEWPORT_SCALING_3D_MODE_OFF;
}
int width;
@@ -141,36 +140,37 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
int render_width;
int render_height;
- if (scaling_enabled) {
- switch (scaling_3d_mode) {
- 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;
- break;
- case RS::VIEWPORT_SCALING_3D_MODE_FSR:
- 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);
- break;
- default:
- // This is an unknown mode.
- WARN_PRINT_ONCE(vformat("Unknown scaling mode: %d. Disabling 3D resolution scaling.", scaling_3d_mode));
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = width;
- render_height = height;
- break;
- }
- } else {
- width = p_viewport->size.width;
- height = p_viewport->size.height;
- render_width = width;
- render_height = height;
+ switch (scaling_3d_mode) {
+ 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;
+ break;
+ case RS::VIEWPORT_SCALING_3D_MODE_FSR:
+ 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);
+ break;
+ case RS::VIEWPORT_SCALING_3D_MODE_OFF:
+ width = p_viewport->size.width;
+ height = p_viewport->size.height;
+ render_width = width;
+ render_height = 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;
+ break;
}
p_viewport->internal_size = Size2(render_width, render_height);
@@ -179,7 +179,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
// to compensate for the loss of sharpness.
const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
- p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count);
+ p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), scaling_3d_mode, p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count);
}
}
}
@@ -236,7 +236,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
}
}
- if (!p_viewport->disable_2d && !p_viewport->disable_environment && RSG::scene->is_scenario(p_viewport->scenario)) {
+ if (!p_viewport->disable_2d && !viewport_is_environment_disabled(p_viewport) && RSG::scene->is_scenario(p_viewport->scenario)) {
RID environment = RSG::scene->scenario_get_environment(p_viewport->scenario);
if (RSG::scene->is_environment(environment)) {
scenario_draw_canvas_bg = RSG::scene->environment_get_background(environment) == RS::ENV_BG_CANVAS;
@@ -992,11 +992,21 @@ void RendererViewport::viewport_set_disable_2d(RID p_viewport, bool p_disable) {
viewport->disable_2d = p_disable;
}
-void RendererViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
+void RendererViewport::viewport_set_environment_mode(RID p_viewport, RS::ViewportEnvironmentMode p_mode) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->disable_environment = p_disable;
+ viewport->disable_environment = p_mode;
+}
+
+bool RendererViewport::viewport_is_environment_disabled(Viewport *viewport) {
+ ERR_FAIL_COND_V(!viewport, false);
+
+ if (viewport->parent.is_valid() && viewport->disable_environment == RS::VIEWPORT_ENVIRONMENT_INHERIT) {
+ Viewport *parent = viewport_owner.get_or_null(viewport->parent);
+ return viewport_is_environment_disabled(parent);
+ }
+ return viewport->disable_environment == RS::VIEWPORT_ENVIRONMENT_DISABLED;
}
void RendererViewport::viewport_set_disable_3d(RID p_viewport, bool p_disable) {
@@ -1138,6 +1148,7 @@ void RendererViewport::viewport_set_screen_space_aa(RID p_viewport, RS::Viewport
void RendererViewport::viewport_set_use_taa(RID p_viewport, bool p_use_taa) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
+ ERR_FAIL_COND_EDMSG(OS::get_singleton()->get_current_rendering_method() != "forward_plus", "TAA is only available when using the Forward+ renderer.");
if (viewport->use_taa == p_use_taa) {
return;
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 9b32cc3774..c24275de6e 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -85,7 +85,7 @@ public:
bool viewport_render_direct_to_screen;
bool disable_2d = false;
- bool disable_environment = false;
+ RS::ViewportEnvironmentMode disable_environment = RS::VIEWPORT_ENVIRONMENT_INHERIT;
bool disable_3d = false;
bool measure_render_time = false;
@@ -238,9 +238,11 @@ public:
const RendererSceneRender::CameraData *viewport_get_prev_camera_data(RID p_viewport);
void viewport_set_disable_2d(RID p_viewport, bool p_disable);
- void viewport_set_disable_environment(RID p_viewport, bool p_disable);
+ void viewport_set_environment_mode(RID p_viewport, RS::ViewportEnvironmentMode p_mode);
void viewport_set_disable_3d(RID p_viewport, bool p_disable);
+ bool viewport_is_environment_disabled(Viewport *viewport);
+
void viewport_attach_camera(RID p_viewport, RID p_camera);
void viewport_set_scenario(RID p_viewport, RID p_scenario);
void viewport_attach_canvas(RID p_viewport, RID p_canvas);
diff --git a/servers/rendering/rendering_device_binds.cpp b/servers/rendering/rendering_device_binds.cpp
index 5967835d03..3678b70254 100644
--- a/servers/rendering/rendering_device_binds.cpp
+++ b/servers/rendering/rendering_device_binds.cpp
@@ -31,6 +31,8 @@
#include "rendering_device_binds.h"
Error RDShaderFile::parse_versions_from_text(const String &p_text, const String p_defines, OpenIncludeFunction p_include_func, void *p_include_func_userdata) {
+ ERR_FAIL_NULL_V(RenderingDevice::get_singleton(), ERR_UNAVAILABLE);
+
Vector<String> lines = p_text.split("\n");
bool reading_versions = false;
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index d053c60b85..bcaaba8d65 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -608,7 +608,7 @@ public:
FUNC1RC(RID, viewport_get_texture, RID)
FUNC2(viewport_set_disable_2d, RID, bool)
- FUNC2(viewport_set_disable_environment, RID, bool)
+ FUNC2(viewport_set_environment_mode, RID, ViewportEnvironmentMode)
FUNC2(viewport_set_disable_3d, RID, bool)
FUNC2(viewport_set_canvas_cull_mask, RID, uint32_t)
@@ -854,7 +854,7 @@ public:
FUNC8(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float, float)
FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
- FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
+ FUNC5(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
FUNC9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int)
FUNC5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID)
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 626da90168..2710724066 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -909,9 +909,6 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
- if (vnode->name == "SCREEN_TEXTURE") {
- r_gen_code.uses_screen_texture_mipmaps = true;
- }
} else {
if (shader->uniforms.has(vnode->name)) {
//its a uniform!
@@ -919,29 +916,22 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (u.texture_order >= 0) {
StringName name = vnode->name;
if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
- name = "SCREEN_TEXTURE";
+ name = "color_buffer";
if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
r_gen_code.uses_screen_texture_mipmaps = true;
}
+ r_gen_code.uses_screen_texture = true;
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
- name = "NORMAL_ROUGHNESS_TEXTURE";
+ name = "normal_roughness_buffer";
+ r_gen_code.uses_normal_roughness_texture = true;
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
- name = "DEPTH_TEXTURE";
+ name = "depth_buffer";
+ r_gen_code.uses_depth_texture = true;
} else {
name = _mkid(vnode->name); //texture, use as is
}
- if (p_default_actions.renames.has(name)) {
- code = p_default_actions.renames[name];
- } else {
- code = name;
- }
-
- if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) {
- *p_actions.usage_flag_pointers[name] = true;
- used_flag_pointers.insert(name);
- }
-
+ code = name;
} else {
//a scalar or vector
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
@@ -1183,9 +1173,10 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += "(";
- // if normal roughness texture is used, we will add logic to automatically switch between
+ // if color backbuffer, depth backbuffer or normal roughness texture is used,
+ // we will add logic to automatically switch between
// sampler2D and sampler2D array and vec2 UV and vec3 UV.
- bool normal_roughness_texture_used = false;
+ bool multiview_uv_needed = false;
for (int i = 1; i < onode->arguments.size(); i++) {
if (i > 1) {
@@ -1230,8 +1221,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
- if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
- //need to map from texture to sampler in order to sample when using Vulkan GLSL
+ if (is_texture_func && i == 1) {
+ // If we're doing a texture lookup we need to check our texture argument
StringName texture_uniform;
bool correct_texture_uniform = false;
@@ -1250,17 +1241,25 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
break;
}
- if (correct_texture_uniform) {
- //TODO Needs to detect screen_texture hint as well
- is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
-
+ if (correct_texture_uniform && !RS::get_singleton()->is_low_end()) {
+ // Need to map from texture to sampler in order to sample when using Vulkan GLSL.
String sampler_name;
+ bool is_depth_texture = false;
+ bool is_normal_roughness_texture = false;
if (actions.custom_samplers.has(texture_uniform)) {
sampler_name = actions.custom_samplers[texture_uniform];
} else {
if (shader->uniforms.has(texture_uniform)) {
- sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat);
+ const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ is_screen_texture = true;
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ is_depth_texture = true;
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ is_normal_roughness_texture = true;
+ }
+ sampler_name = _get_sampler_name(u.filter, u.repeat);
} else {
bool found = false;
@@ -1287,24 +1286,40 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
String data_type_name = "";
- if (texture_uniform == "NORMAL_ROUGHNESS_TEXTURE") {
+ if (actions.check_multiview_samplers && (is_screen_texture || is_depth_texture || is_normal_roughness_texture)) {
data_type_name = "multiviewSampler";
- normal_roughness_texture_used = true;
+ multiview_uv_needed = true;
} else {
data_type_name = ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype());
}
code += data_type_name + "(" + node_code + ", " + sampler_name + ")";
+ } else if (actions.check_multiview_samplers && correct_texture_uniform && RS::get_singleton()->is_low_end()) {
+ // Texture function on low end hardware (i.e. OpenGL).
+ // We just need to know if the texture supports multiview.
+
+ if (shader->uniforms.has(texture_uniform)) {
+ const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[texture_uniform];
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ multiview_uv_needed = true;
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ multiview_uv_needed = true;
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ multiview_uv_needed = true;
+ }
+ }
+
+ code += node_code;
} else {
code += node_code;
}
- } else {
- if (normal_roughness_texture_used && i == 2) {
- // UV coordinate after using normal roughness texture.
- node_code = "normal_roughness_uv(" + node_code + ".xy)";
- }
+ } else if (multiview_uv_needed && i == 2) {
+ // UV coordinate after using color, depth or normal roughness texture.
+ node_code = "multiview_uv(" + node_code + ".xy)";
code += node_code;
+ } else {
+ code += node_code;
}
}
code += ")";
@@ -1515,6 +1530,9 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
r_gen_code.uses_vertex_time = false;
r_gen_code.uses_global_textures = false;
r_gen_code.uses_screen_texture_mipmaps = false;
+ r_gen_code.uses_screen_texture = false;
+ r_gen_code.uses_depth_texture = false;
+ r_gen_code.uses_normal_roughness_texture = false;
used_name_defines.clear();
used_rmode_defines.clear();
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index eeb2916160..3bb29a545b 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -81,6 +81,9 @@ public:
bool uses_fragment_time;
bool uses_vertex_time;
bool uses_screen_texture_mipmaps;
+ bool uses_screen_texture;
+ bool uses_depth_texture;
+ bool uses_normal_roughness_texture;
};
struct DefaultIdentifierActions {
@@ -98,6 +101,7 @@ public:
String instance_uniform_index_variable;
uint32_t base_varying_index = 0;
bool apply_luminance_multiplier = false;
+ bool check_multiview_samplers = false;
};
private:
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index 59a2ff66f3..11a9303f11 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -90,8 +90,9 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"IDENTIFIER",
"TRUE",
"FALSE",
- "REAL_CONSTANT",
+ "FLOAT_CONSTANT",
"INT_CONSTANT",
+ "UINT_CONSTANT",
"TYPE_VOID",
"TYPE_BOOL",
"TYPE_BVEC2",
@@ -126,6 +127,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"INTERPOLATION_FLAT",
"INTERPOLATION_SMOOTH",
"CONST",
+ "STRUCT",
"PRECISION_LOW",
"PRECISION_MID",
"PRECISION_HIGH",
@@ -169,6 +171,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"CF_DO",
"CF_SWITCH",
"CF_CASE",
+ "CF_DEFAULT",
"CF_BREAK",
"CF_CONTINUE",
"CF_RETURN",
@@ -185,19 +188,26 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"SEMICOLON",
"PERIOD",
"UNIFORM",
+ "UNIFORM_GROUP",
"INSTANCE",
"GLOBAL",
"VARYING",
- "IN",
- "OUT",
- "INOUT",
+ "ARG_IN",
+ "ARG_OUT",
+ "ARG_INOUT",
"RENDER_MODE",
- "SOURCE_COLOR",
"HINT_DEFAULT_WHITE_TEXTURE",
"HINT_DEFAULT_BLACK_TEXTURE",
"HINT_DEFAULT_TRANSPARENT_TEXTURE",
"HINT_NORMAL_TEXTURE",
+ "HINT_ROUGHNESS_NORMAL_TEXTURE",
+ "HINT_ROUGHNESS_R",
+ "HINT_ROUGHNESS_G",
+ "HINT_ROUGHNESS_B",
+ "HINT_ROUGHNESS_A",
+ "HINT_ROUGHNESS_GRAY",
"HINT_ANISOTROPY_TEXTURE",
+ "HINT_SOURCE_COLOR",
"HINT_RANGE",
"HINT_INSTANCE_INDEX",
"HINT_SCREEN_TEXTURE",
@@ -612,7 +622,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
char_idx += 2;
include_positions.resize(include_positions.size() - 1); // Pop back.
- tk_line = include_positions[include_positions.size() - 1].line; // Restore line.
+ tk_line = include_positions[include_positions.size() - 1].line - 1; // Restore line.
} else {
return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)");
@@ -2827,6 +2837,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
{ "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ // dFdxCoarse
+
+ { "dFdxCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // dFdxFine
+
+ { "dFdxFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdxFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
// dFdy
{ "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
@@ -2834,6 +2858,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
{ "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ // dFdyCoarse
+
+ { "dFdyCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // dFdyFine
+
+ { "dFdyFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdyFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
// fwidth
{ "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
@@ -2841,6 +2879,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
{ "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ // fwidthCoarse
+
+ { "fwidthCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
+ // fwidthFine
+
+ { "fwidthFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidthFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+
// Sub-functions.
// array
@@ -5399,6 +5451,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
} else {
if (!_find_identifier(p_block, false, p_function_info, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) {
+ if (identifier == "SCREEN_TEXTURE" || identifier == "DEPTH_TEXTURE" || identifier == "NORMAL_ROUGHNESS_TEXTURE") {
+ String name = String(identifier);
+ String name_lower = name.to_lower();
+ _set_error(vformat(RTR("%s has been removed in favor of using hint_%s with a uniform.\nTo continue with minimal code changes add 'uniform sampler2D %s : hint_%s, filter_linear_mipmap;' near the top of your shader."), name, name_lower, name, name_lower));
+ return nullptr;
+ }
_set_error(vformat(RTR("Unknown identifier in expression: '%s'."), String(identifier)));
return nullptr;
}
@@ -8227,6 +8285,10 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
_set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
return ERR_PARSE_ERROR;
}
+ if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
+ _set_error(RTR("Uniform instances are not supported in gl_compatibility shaders."));
+ return ERR_PARSE_ERROR;
+ }
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
tk = _get_token();
if (tk.type != TK_UNIFORM) {
@@ -8691,14 +8753,21 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_HINT_SCREEN_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE;
--texture_uniforms;
+ --texture_binding;
} break;
case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE;
--texture_uniforms;
+ --texture_binding;
+ if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
+ _set_error(RTR("'hint_normal_roughness_texture is not supported in gl_compatibility shaders."));
+ return ERR_PARSE_ERROR;
+ }
} break;
case TK_HINT_DEPTH_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE;
--texture_uniforms;
+ --texture_binding;
} break;
case TK_FILTER_NEAREST: {
new_filter = FILTER_NEAREST;
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
index 40c8acffe5..b45a7c0db3 100644
--- a/servers/rendering/shader_preprocessor.cpp
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -78,19 +78,46 @@ char32_t ShaderPreprocessor::Tokenizer::peek() {
return 0;
}
+int ShaderPreprocessor::Tokenizer::consume_line_continuations(int p_offset) {
+ int skips = 0;
+
+ for (int i = index + p_offset; i < size; i++) {
+ char32_t c = code[i];
+ if (c == '\\') {
+ if (i + 1 < size && code[i + 1] == '\n') {
+ // This line ends with "\" and "\n" continuation.
+ add_generated(Token('\n', line));
+ line++;
+ skips++;
+
+ i = i + 2;
+ index = i;
+ } else {
+ break;
+ }
+ } else if (!is_whitespace(c)) {
+ break;
+ }
+ }
+ return skips;
+}
+
LocalVector<ShaderPreprocessor::Token> ShaderPreprocessor::Tokenizer::advance(char32_t p_what) {
LocalVector<ShaderPreprocessor::Token> tokens;
while (index < size) {
char32_t c = code[index++];
-
- tokens.push_back(ShaderPreprocessor::Token(c, line));
+ if (c == '\\' && consume_line_continuations(-1) > 0) {
+ continue;
+ }
if (c == '\n') {
add_generated(ShaderPreprocessor::Token('\n', line));
line++;
}
+ tokens.push_back(ShaderPreprocessor::Token(c, line));
+
if (c == p_what || c == 0) {
return tokens;
}
@@ -104,6 +131,11 @@ void ShaderPreprocessor::Tokenizer::skip_whitespace() {
}
}
+bool ShaderPreprocessor::Tokenizer::consume_empty_line() {
+ // Read until newline and return true if the content was all whitespace/empty.
+ return tokens_to_string(advance('\n')).strip_edges().size() == 0;
+}
+
String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_started) {
if (r_is_cursor != nullptr) {
*r_is_cursor = false;
@@ -113,6 +145,10 @@ String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_s
while (true) {
char32_t c = peek();
+ if (c == '\\' && consume_line_continuations(0) > 0) {
+ continue;
+ }
+
if (is_char_end(c) || c == '(' || c == ')' || c == ',' || c == ';') {
break;
}
@@ -146,8 +182,10 @@ String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_s
String ShaderPreprocessor::Tokenizer::peek_identifier() {
const int original = index;
+ const int original_line = line;
String id = get_identifier();
index = original;
+ line = original_line;
return id;
}
@@ -330,8 +368,8 @@ String ShaderPreprocessor::vector_to_string(const LocalVector<char32_t> &p_v, in
String ShaderPreprocessor::tokens_to_string(const LocalVector<Token> &p_tokens) {
LocalVector<char32_t> result;
- for (uint32_t i = 0; i < p_tokens.size(); i++) {
- result.push_back(p_tokens[i].text);
+ for (const Token &token : p_tokens) {
+ result.push_back(token.text);
}
return vector_to_string(result);
}
@@ -485,7 +523,9 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
state->previous_region->to_line = line - 1;
}
- p_tokenizer->advance('\n');
+ if (!p_tokenizer->consume_empty_line()) {
+ set_error(RTR("Invalid else."), p_tokenizer->get_line());
+ }
bool skip = false;
for (int i = 0; i < state->current_branch->conditions.size(); i++) {
@@ -508,17 +548,21 @@ void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
}
void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
state->condition_depth--;
if (state->condition_depth < 0) {
- set_error(RTR("Unmatched endif."), p_tokenizer->get_line());
+ set_error(RTR("Unmatched endif."), line);
return;
}
if (state->previous_region != nullptr) {
- state->previous_region->to_line = p_tokenizer->get_line() - 1;
+ state->previous_region->to_line = line - 1;
state->previous_region = state->previous_region->parent;
}
- p_tokenizer->advance('\n');
+ if (!p_tokenizer->consume_empty_line()) {
+ set_error(RTR("Invalid endif."), line);
+ }
state->current_branch = state->current_branch->parent;
state->branches.pop_back();
@@ -574,12 +618,10 @@ void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) {
return;
}
- p_tokenizer->skip_whitespace();
- if (!is_char_end(p_tokenizer->peek())) {
+ if (!p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid ifdef."), line);
return;
}
- p_tokenizer->advance('\n');
bool success = state->defines.has(label);
start_branch_condition(p_tokenizer, success);
@@ -598,12 +640,10 @@ void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) {
return;
}
- p_tokenizer->skip_whitespace();
- if (!is_char_end(p_tokenizer->peek())) {
+ if (!p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid ifndef."), line);
return;
}
- p_tokenizer->advance('\n');
bool success = !state->defines.has(label);
start_branch_condition(p_tokenizer, success);
@@ -628,13 +668,17 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
}
}
path = path.substr(0, path.length() - 1);
- p_tokenizer->skip_whitespace();
- if (path.is_empty() || !is_char_end(p_tokenizer->peek())) {
+ if (path.is_empty() || !p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid path."), line);
return;
}
+ path = path.simplify_path();
+ if (path.is_relative_path()) {
+ path = state->current_filename.get_base_dir().path_join(path);
+ }
+
Ref<Resource> res = ResourceLoader::load(path);
if (res.is_null()) {
set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line);
@@ -728,25 +772,24 @@ void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) {
return;
}
- p_tokenizer->advance('\n');
+ if (!p_tokenizer->consume_empty_line()) {
+ set_error(RTR("Invalid pragma directive."), line);
+ return;
+ }
}
void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) {
const int line = p_tokenizer->get_line();
const String label = p_tokenizer->get_identifier();
- if (label.is_empty() || !state->defines.has(label)) {
- set_error(RTR("Invalid name."), line);
- return;
- }
-
- p_tokenizer->skip_whitespace();
- if (!is_char_end(p_tokenizer->peek())) {
+ if (label.is_empty() || !p_tokenizer->consume_empty_line()) {
set_error(RTR("Invalid undef."), line);
return;
}
- memdelete(state->defines[label]);
- state->defines.erase(label);
+ if (state->defines.has(label)) {
+ memdelete(state->defines[label]);
+ state->defines.erase(label);
+ }
}
void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent_region) {
@@ -957,15 +1000,57 @@ bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_num
String body = define->body;
if (define->arguments.size() > 0) {
// Complex macro with arguments.
- int args_start = index + key.length();
- int args_end = p_line.find(")", args_start);
- if (args_start == -1 || args_end == -1) {
- set_error(RTR("Missing macro argument parenthesis."), p_line_number);
- return false;
+
+ int args_start = -1;
+ int args_end = -1;
+ int brackets_open = 0;
+ Vector<String> args;
+ for (int i = index_start - 1; i < p_line.length(); i++) {
+ bool add_argument = false;
+ bool reached_end = false;
+ char32_t c = p_line[i];
+
+ if (c == '(') {
+ brackets_open++;
+ if (brackets_open == 1) {
+ args_start = i + 1;
+ args_end = -1;
+ }
+ } else if (c == ')') {
+ brackets_open--;
+ if (brackets_open == 0) {
+ args_end = i;
+ add_argument = true;
+ reached_end = true;
+ }
+ } else if (c == ',') {
+ if (brackets_open == 1) {
+ args_end = i;
+ add_argument = true;
+ }
+ }
+
+ if (add_argument) {
+ if (args_start == -1 || args_end == -1) {
+ set_error(RTR("Invalid macro argument list."), p_line_number);
+ return false;
+ }
+
+ String arg = p_line.substr(args_start, args_end - args_start).strip_edges();
+ if (arg.is_empty()) {
+ set_error(RTR("Invalid macro argument."), p_line_number);
+ return false;
+ }
+ args.append(arg);
+
+ args_start = args_end + 1;
+ }
+
+ if (reached_end) {
+ break;
+ }
}
- String values = result.substr(args_start + 1, args_end - (args_start + 1));
- Vector<String> args = values.split(",");
if (args.size() != define->arguments.size()) {
set_error(RTR("Invalid macro argument count."), p_line_number);
return false;
@@ -987,9 +1072,6 @@ bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_num
result = result.substr(0, index) + " " + body + " " + result.substr(args_end + 1, result.length());
} else {
result = result.substr(0, index) + body + result.substr(index + key.length(), result.length() - (index + key.length()));
- // Manually reset index_start to where the body value of the define finishes.
- // This ensures we don't skip another instance of this macro in the string.
- index_start = index + body.length() + 1;
}
r_expanded = result;
@@ -1081,21 +1163,17 @@ ShaderPreprocessor::Define *ShaderPreprocessor::create_define(const String &p_bo
return define;
}
-void ShaderPreprocessor::clear() {
- if (state_owner && state != nullptr) {
+void ShaderPreprocessor::clear_state() {
+ if (state != nullptr) {
for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
memdelete(E->get());
}
-
- memdelete(state);
+ state->defines.clear();
}
- state_owner = false;
state = nullptr;
}
Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, String &r_result) {
- clear();
-
output.clear();
state = p_state;
@@ -1242,6 +1320,9 @@ Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filen
}
}
}
+
+ clear_state();
+
return err;
}
@@ -1273,5 +1354,4 @@ ShaderPreprocessor::ShaderPreprocessor() {
}
ShaderPreprocessor::~ShaderPreprocessor() {
- clear();
}
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
index f5902c64ca..2b7d2c274e 100644
--- a/servers/rendering/shader_preprocessor.h
+++ b/servers/rendering/shader_preprocessor.h
@@ -93,11 +93,13 @@ private:
int get_line() const;
int get_index() const;
char32_t peek();
+ int consume_line_continuations(int p_offset);
void get_and_clear_generated(Vector<Token> *r_out);
void backtrack(char32_t p_what);
LocalVector<Token> advance(char32_t p_what);
void skip_whitespace();
+ bool consume_empty_line();
String get_identifier(bool *r_is_cursor = nullptr, bool p_started = false);
String peek_identifier();
Token get_token();
@@ -167,7 +169,6 @@ private:
private:
LocalVector<char32_t> output;
State *state = nullptr;
- bool state_owner = false;
private:
static bool is_char_word(char32_t p_char);
@@ -211,7 +212,7 @@ private:
static Define *create_define(const String &p_body);
- void clear();
+ void clear_state();
Error preprocess(State *p_state, const String &p_code, String &r_result);
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 38dc806370..ba39328b2e 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -138,9 +138,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_ROUGHNESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
- shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
@@ -267,7 +264,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
- shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].main_function = true;
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
index 704c2e015c..76e46a696a 100644
--- a/servers/rendering/storage/mesh_storage.h
+++ b/servers/rendering/storage/mesh_storage.h
@@ -83,6 +83,7 @@ public:
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) = 0;
virtual void mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) = 0;
virtual void mesh_instance_check_for_update(RID p_mesh_instance) = 0;
+ virtual void mesh_instance_set_canvas_item_transform(RID p_mesh_instance, const Transform2D &p_transform) = 0;
virtual void update_mesh_instances() = 0;
/* MULTIMESH API */
diff --git a/servers/rendering/storage/render_scene_buffers.cpp b/servers/rendering/storage/render_scene_buffers.cpp
index 1320199833..6369139aa6 100644
--- a/servers/rendering/storage/render_scene_buffers.cpp
+++ b/servers/rendering/storage/render_scene_buffers.cpp
@@ -34,8 +34,8 @@ void RenderSceneBuffers::_bind_methods() {
ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure);
}
-void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
- GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
+void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+ GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_scaling_3d_mode, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
};
void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) {
diff --git a/servers/rendering/storage/render_scene_buffers.h b/servers/rendering/storage/render_scene_buffers.h
index 83fc78ca1c..cf96a9f372 100644
--- a/servers/rendering/storage/render_scene_buffers.h
+++ b/servers/rendering/storage/render_scene_buffers.h
@@ -40,7 +40,7 @@ class RenderSceneBuffers : public RefCounted {
protected:
static void _bind_methods();
- GDVIRTUAL10(_configure, RID, Size2i, Size2i, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
+ GDVIRTUAL11(_configure, RID, Size2i, Size2i, RS::ViewportScaling3DMode, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
GDVIRTUAL1(_set_fsr_sharpness, float)
GDVIRTUAL1(_set_texture_mipmap_bias, float)
GDVIRTUAL1(_set_use_debanding, bool)
@@ -49,7 +49,7 @@ public:
RenderSceneBuffers(){};
virtual ~RenderSceneBuffers(){};
- virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
+ virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, RS::ViewportScaling3DMode p_scaling_3d_mode, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
// for those settings that are unlikely to require buffers to be recreated, we'll add setters
virtual void set_fsr_sharpness(float p_fsr_sharpness);
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index 92149b0064..4c4a84d04e 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -127,6 +127,7 @@ public:
virtual RID decal_instance_create(RID p_decal) = 0;
virtual void decal_instance_free(RID p_decal_instance) = 0;
virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) = 0;
+ virtual void decal_instance_set_sorting_offset(RID p_decal_instance, float p_sorting_offset) = 0;
/* RENDER TARGET */
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 14d8d035e2..cea7912574 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -996,6 +996,7 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
if (index_array_len) {
List<Variant> keys;
p_lods.get_key_list(&keys);
+ keys.sort(); // otherwise lod levels may get skipped
for (const Variant &E : keys) {
float distance = E;
ERR_CONTINUE(distance <= 0.0);
@@ -1826,6 +1827,7 @@ void RenderingServer::_bind_methods() {
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_2D_VERTICES);
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_DYNAMIC_UPDATE);
BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_8_BONE_WEIGHTS);
+ BIND_BITFIELD_FLAG(ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY);
BIND_ENUM_CONSTANT(PRIMITIVE_POINTS);
BIND_ENUM_CONSTANT(PRIMITIVE_LINES);
@@ -2198,7 +2200,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture);
ClassDB::bind_method(D_METHOD("viewport_set_disable_3d", "viewport", "disable"), &RenderingServer::viewport_set_disable_3d);
ClassDB::bind_method(D_METHOD("viewport_set_disable_2d", "viewport", "disable"), &RenderingServer::viewport_set_disable_2d);
- ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &RenderingServer::viewport_set_disable_environment);
+ ClassDB::bind_method(D_METHOD("viewport_set_environment_mode", "viewport", "mode"), &RenderingServer::viewport_set_environment_mode);
ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &RenderingServer::viewport_attach_camera);
ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &RenderingServer::viewport_set_scenario);
ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &RenderingServer::viewport_attach_canvas);
@@ -2253,6 +2255,11 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER);
BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME);
+ BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_ENABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_INHERIT);
+ BIND_ENUM_CONSTANT(VIEWPORT_ENVIRONMENT_MAX);
+
BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_100_PERCENT);
BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_120_PERCENT);
BIND_ENUM_CONSTANT(VIEWPORT_SDF_OVERSIZE_150_PERCENT);
@@ -2592,8 +2599,8 @@ void RenderingServer::_bind_methods() {
/* Primitives */
- ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(-1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect);
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
@@ -2601,7 +2608,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
- ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture"), &RenderingServer::canvas_item_add_primitive);
ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture"), &RenderingServer::canvas_item_add_polygon, DEFVAL(Vector<Point2>()), DEFVAL(RID()));
ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count"), &RenderingServer::canvas_item_add_triangle_array, DEFVAL(Vector<Point2>()), DEFVAL(Vector<int>()), DEFVAL(Vector<float>()), DEFVAL(RID()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture"), &RenderingServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()));
@@ -2800,9 +2807,7 @@ void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry
Vector<Vector3> vertices;
Vector<Vector3> normals;
- for (uint32_t i = 0; i < p_mesh_data.faces.size(); i++) {
- const Geometry3D::MeshData::Face &f = p_mesh_data.faces[i];
-
+ for (const Geometry3D::MeshData::Face &f : p_mesh_data.faces) {
for (uint32_t j = 2; j < f.indices.size(); j++) {
vertices.push_back(p_mesh_data.vertices[f.indices[0]]);
normals.push_back(f.plane.normal);
@@ -2849,10 +2854,8 @@ RenderingServer::RenderingServer() {
}
void RenderingServer::init() {
- GLOBAL_DEF_RST("rendering/textures/vram_compression/import_bptc", false);
- GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc", true);
- GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc", false);
- GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2", true);
+ GLOBAL_DEF_RST("rendering/textures/vram_compression/import_s3tc_bptc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_S3TC_BPTC);
+ GLOBAL_DEF_RST("rendering/textures/vram_compression/import_etc2_astc", OS::get_singleton()->get_preferred_texture_format() == OS::PREFERRED_TEXTURE_FORMAT_ETC2_ASTC);
GLOBAL_DEF("rendering/textures/lossless_compression/force_png", false);
@@ -2875,7 +2878,7 @@ void RenderingServer::init() {
GLOBAL_DEF("rendering/2d/shadow_atlas/size", 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, "1024,1048576,1"), 16384);
+ GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/gl_compatibility/item_buffer_size", PROPERTY_HINT_RANGE, "128,1048576,1"), 16384);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true);
@@ -2961,9 +2964,9 @@ void RenderingServer::init() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/volume_depth", PROPERTY_HINT_RANGE, "16,512,1"), 64);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/environment/volumetric_fog/use_filter", PROPERTY_HINT_ENUM, "No (Faster),Yes (Higher Quality)"), 1);
- GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/update_iterations_per_frame", PROPERTY_HINT_RANGE, "0,1024,1"), 10);
- GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/threaded_cull_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"), 1000);
- GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/limits/forward_renderer/threaded_render_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"), 500);
+ GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/update_iterations_per_frame", PROPERTY_HINT_RANGE, "0,1024,1"), 10);
+ GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/spatial_indexer/threaded_cull_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"), 1000);
+ GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/limits/forward_renderer/threaded_render_minimum_instances", PROPERTY_HINT_RANGE, "32,65536,1"), 500);
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"), 512);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 6efe28a847..b416ed30e2 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -802,7 +802,8 @@ public:
enum ViewportScaling3DMode {
VIEWPORT_SCALING_3D_MODE_BILINEAR,
VIEWPORT_SCALING_3D_MODE_FSR,
- VIEWPORT_SCALING_3D_MODE_MAX
+ VIEWPORT_SCALING_3D_MODE_MAX,
+ VIEWPORT_SCALING_3D_MODE_OFF = 255, // for internal use only
};
virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0;
@@ -839,7 +840,14 @@ public:
virtual RID viewport_get_texture(RID p_viewport) const = 0;
- virtual void viewport_set_disable_environment(RID p_viewport, bool p_disable) = 0;
+ enum ViewportEnvironmentMode {
+ VIEWPORT_ENVIRONMENT_DISABLED,
+ VIEWPORT_ENVIRONMENT_ENABLED,
+ VIEWPORT_ENVIRONMENT_INHERIT,
+ VIEWPORT_ENVIRONMENT_MAX,
+ };
+
+ virtual void viewport_set_environment_mode(RID p_viewport, ViewportEnvironmentMode p_mode) = 0;
virtual void viewport_set_disable_3d(RID p_viewport, bool p_disable) = 0;
virtual void viewport_set_disable_2d(RID p_viewport, bool p_disable) = 0;
@@ -1333,9 +1341,9 @@ public:
NINE_PATCH_TILE_FIT,
};
- virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0, bool p_antialiased = false) = 0;
- virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0, bool p_antialiased = false) = 0;
- virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0) = 0;
+ virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = -1.0, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0, bool p_antialiased = false) = 0;
+ virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = -1.0) = 0;
virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0;
virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
@@ -1343,7 +1351,7 @@ public:
virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0, float p_scale = 1.0) = 0;
virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0;
- virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0;
+ virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0;
virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1) = 0;
virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID()) = 0;
@@ -1638,6 +1646,7 @@ VARIANT_ENUM_CAST(RenderingServer::FogVolumeShape);
VARIANT_ENUM_CAST(RenderingServer::ViewportScaling3DMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode);
+VARIANT_ENUM_CAST(RenderingServer::ViewportEnvironmentMode);
VARIANT_ENUM_CAST(RenderingServer::ViewportMSAA);
VARIANT_ENUM_CAST(RenderingServer::ViewportScreenSpaceAA);
VARIANT_ENUM_CAST(RenderingServer::ViewportRenderInfo);
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 997b83e32d..cbf37f25d6 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -1373,8 +1373,8 @@ String TextServerExtension::string_to_lower(const String &p_string, const String
return p_string;
}
-TypedArray<Vector2i> TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- TypedArray<Vector2i> ret;
+TypedArray<Vector3i> TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector3i> ret;
GDVIRTUAL_CALL(_parse_structured_text, p_parser_type, p_args, p_text, ret);
return ret;
}
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index fb784f5471..8536836983 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -521,8 +521,8 @@ public:
GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &);
GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &);
- TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
- GDVIRTUAL3RC(TypedArray<Vector2i>, _parse_structured_text, StructuredTextParser, const Array &, const String &);
+ TypedArray<Vector3i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ GDVIRTUAL3RC(TypedArray<Vector3i>, _parse_structured_text, StructuredTextParser, const Array &, const String &);
virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
virtual bool spoof_check(const String &p_string) const override;
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index d339533688..027109b67d 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -483,6 +483,7 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
BIND_ENUM_CONSTANT(DIRECTION_RTL);
+ BIND_ENUM_CONSTANT(DIRECTION_INHERITED);
/* Orientation */
BIND_ENUM_CONSTANT(ORIENTATION_HORIZONTAL);
@@ -599,7 +600,7 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
- BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE);
+ BIND_ENUM_CONSTANT(STRUCTURED_TEXT_GDSCRIPT);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
}
@@ -1692,22 +1693,22 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result;
}
-TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- TypedArray<Vector2i> ret;
+TypedArray<Vector3i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector3i> ret;
switch (p_parser_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) {
if (prev != i) {
- ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_FILE: {
@@ -1715,14 +1716,14 @@ TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_pa
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) {
if (prev != i) {
- ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_EMAIL: {
@@ -1731,19 +1732,19 @@ TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_pa
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '@') && local) { // Add full "local" as single context.
local = false;
- ret.push_back(Vector2i(prev, i));
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
} else if (!local && (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
if (prev != i) {
- ret.push_back(Vector2i(prev, i));
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
}
- ret.push_back(Vector2i(i, i + 1));
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
prev = i + 1;
}
}
if (prev != p_text.length()) {
- ret.push_back(Vector2i(prev, p_text.length()));
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
}
} break;
case STRUCTURED_TEXT_LIST: {
@@ -1752,18 +1753,97 @@ TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_pa
int prev = 0;
for (int i = 0; i < tags.size(); i++) {
if (prev != i) {
- ret.push_back(Vector2i(prev, prev + tags[i].length()));
+ ret.push_back(Vector3i(prev, prev + tags[i].length(), TextServer::DIRECTION_INHERITED));
}
- ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1));
+ ret.push_back(Vector3i(prev + tags[i].length(), prev + tags[i].length() + 1, TextServer::DIRECTION_INHERITED));
prev = prev + tags[i].length() + 1;
}
}
} break;
+ case STRUCTURED_TEXT_GDSCRIPT: {
+ bool in_string_literal = false;
+ bool in_string_literal_single = false;
+ bool in_id = false;
+
+ int prev = 0;
+ for (int i = 0; i < p_text.length(); i++) {
+ char32_t c = p_text[i];
+ if (in_string_literal) {
+ if (c == '\\') {
+ i++;
+ continue; // Skip escaped chars.
+ } else if (c == '\"') {
+ // String literal end, push string and ".
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal = false;
+ }
+ } else if (in_string_literal_single) {
+ if (c == '\\') {
+ i++;
+ continue; // Skip escaped chars.
+ } else if (c == '\'') {
+ // String literal end, push string and '.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal_single = false;
+ }
+ } else if (in_id) {
+ if (!is_unicode_identifier_continue(c)) {
+ // End of id, push id.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i;
+ in_id = false;
+ }
+ } else if (is_unicode_identifier_start(c)) {
+ // Start of new id, push prev element.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i;
+ in_id = true;
+ } else if (c == '\"') {
+ // String literal start, push prev element and ".
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal = true;
+ } else if (c == '\'') {
+ // String literal start, push prev element and '.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ in_string_literal_single = true;
+ } else if (c == '#') {
+ // Start of comment, push prev element and #, skip the rest of the text.
+ if (prev != i) {
+ ret.push_back(Vector3i(prev, i, TextServer::DIRECTION_AUTO));
+ }
+ prev = i + 1;
+ ret.push_back(Vector3i(i, i + 1, TextServer::DIRECTION_LTR));
+ break;
+ }
+ }
+ if (prev < p_text.length()) {
+ ret.push_back(Vector3i(prev, p_text.length(), TextServer::DIRECTION_AUTO));
+ }
+ } break;
case STRUCTURED_TEXT_CUSTOM:
- case STRUCTURED_TEXT_NONE:
case STRUCTURED_TEXT_DEFAULT:
default: {
- ret.push_back(Vector2i(0, p_text.length()));
+ ret.push_back(Vector3i(0, p_text.length(), TextServer::DIRECTION_INHERITED));
}
}
return ret;
diff --git a/servers/text_server.h b/servers/text_server.h
index a56c7d8b23..a91d367e97 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -65,7 +65,8 @@ public:
enum Direction {
DIRECTION_AUTO,
DIRECTION_LTR,
- DIRECTION_RTL
+ DIRECTION_RTL,
+ DIRECTION_INHERITED,
};
enum Orientation {
@@ -198,7 +199,7 @@ public:
STRUCTURED_TEXT_FILE,
STRUCTURED_TEXT_EMAIL,
STRUCTURED_TEXT_LIST,
- STRUCTURED_TEXT_NONE,
+ STRUCTURED_TEXT_GDSCRIPT,
STRUCTURED_TEXT_CUSTOM
};
@@ -505,7 +506,7 @@ public:
virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0;
- TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ TypedArray<Vector3i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
virtual void cleanup() {}
diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp
index 87c1697a35..ffb89fc385 100644
--- a/servers/xr/xr_positional_tracker.cpp
+++ b/servers/xr/xr_positional_tracker.cpp
@@ -67,8 +67,8 @@ void XRPositionalTracker::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_input", "name", "value"), &XRPositionalTracker::set_input);
ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::STRING, "name")));
ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name")));
- ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
- ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector")));
+ ADD_SIGNAL(MethodInfo("input_float_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value")));
+ ADD_SIGNAL(MethodInfo("input_vector2_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector")));
ADD_SIGNAL(MethodInfo("profile_changed", PropertyInfo(Variant::STRING, "role")));
};
@@ -203,12 +203,12 @@ void XRPositionalTracker::set_input(const StringName &p_action_name, const Varia
// TODO discuss whether we also want to create and emit an InputEventXRButton event
} break;
case Variant::FLOAT: {
- emit_signal(SNAME("input_value_changed"), p_action_name, p_value);
+ emit_signal(SNAME("input_float_changed"), p_action_name, p_value);
// TODO discuss whether we also want to create and emit an InputEventXRValue event
} break;
case Variant::VECTOR2: {
- emit_signal(SNAME("input_axis_changed"), p_action_name, p_value);
+ emit_signal(SNAME("input_vector2_changed"), p_action_name, p_value);
// TODO discuss whether we also want to create and emit an InputEventXRAxis event
} break;
diff --git a/servers/xr_server.h b/servers/xr_server.h
index 086a18c111..04cf6c1d1e 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -111,7 +111,7 @@ public:
Most VR platforms, and our assumption, is that 1 unit in our virtual world equates to 1 meter in the real mode.
This scale basically effects the unit size relationship to real world size.
- I may remove access to this property in GDScript in favour of exposing it on the XROrigin3D node
+ I may remove access to this property in GDScript in favor of exposing it on the XROrigin3D node
*/
double get_world_scale() const;
void set_world_scale(double p_world_scale);