diff options
Diffstat (limited to 'servers')
114 files changed, 5853 insertions, 4041 deletions
diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp index b83b41a571..b87cdd6d9f 100644 --- a/servers/camera_server.cpp +++ b/servers/camera_server.cpp @@ -105,10 +105,7 @@ void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) { // add our feed feeds.push_back(p_feed); -// record for debugging -#ifdef DEBUG_ENABLED - print_line("Registered camera " + p_feed->get_name() + " with id " + itos(p_feed->get_id()) + " position " + itos(p_feed->get_position()) + " at index " + itos(feeds.size() - 1)); -#endif + print_verbose("CameraServer: Registered camera " + p_feed->get_name() + " with ID " + itos(p_feed->get_id()) + " and position " + itos(p_feed->get_position()) + " at index " + itos(feeds.size() - 1)); // let whomever is interested know emit_signal(SNAME("camera_feed_added"), p_feed->get_id()); @@ -119,10 +116,7 @@ void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) { if (feeds[i] == p_feed) { int feed_id = p_feed->get_id(); -// record for debugging -#ifdef DEBUG_ENABLED - print_line("Removed camera " + p_feed->get_name() + " with id " + itos(feed_id) + " position " + itos(p_feed->get_position())); -#endif + print_verbose("CameraServer: Removed camera " + p_feed->get_name() + " with ID " + itos(feed_id) + " and position " + itos(p_feed->get_position())); // remove it from our array, if this results in our feed being unreferenced it will be destroyed feeds.remove_at(i); diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 22f42ca343..dda8e29b6a 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -44,37 +44,37 @@ DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[Displa int DisplayServer::server_create_count = 1; -int DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); return -1; } -int DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); return -1; } -int DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); return -1; } -int DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); return -1; } -int DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); return -1; } -int DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); return -1; } -int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) { +int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) { WARN_PRINT("Global menus not supported by this display server."); return -1; } @@ -103,6 +103,10 @@ void DisplayServer::global_menu_set_item_callback(const String &p_menu_root, int WARN_PRINT("Global menus not supported by this display server."); } +void DisplayServer::global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback) { + WARN_PRINT("Global menus not supported by this display server."); +} + bool DisplayServer::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const { WARN_PRINT("Global menus not supported by this display server."); return false; @@ -123,6 +127,11 @@ Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root, return Callable(); } +Callable DisplayServer::global_menu_get_item_key_callback(const String &p_menu_root, int p_idx) const { + WARN_PRINT("Global menus not supported by this display server."); + return Callable(); +} + Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const { WARN_PRINT("Global menus not supported by this display server."); return Variant(); @@ -527,14 +536,14 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature); ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name); - ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("global_menu_add_icon_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("global_menu_add_icon_check_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("global_menu_add_radio_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_radio_check_item, 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", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_radio_check_item, 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", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_multistate_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu", "index"), &DisplayServer::global_menu_add_submenu_item, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("global_menu_add_icon_item", "menu_root", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1)); + 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_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); @@ -544,6 +553,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_is_item_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checkable); ClassDB::bind_method(D_METHOD("global_menu_is_item_radio_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_radio_checkable); ClassDB::bind_method(D_METHOD("global_menu_get_item_callback", "menu_root", "idx"), &DisplayServer::global_menu_get_item_callback); + ClassDB::bind_method(D_METHOD("global_menu_get_item_key_callback", "menu_root", "idx"), &DisplayServer::global_menu_get_item_key_callback); ClassDB::bind_method(D_METHOD("global_menu_get_item_tag", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tag); ClassDB::bind_method(D_METHOD("global_menu_get_item_text", "menu_root", "idx"), &DisplayServer::global_menu_get_item_text); ClassDB::bind_method(D_METHOD("global_menu_get_item_submenu", "menu_root", "idx"), &DisplayServer::global_menu_get_item_submenu); @@ -559,6 +569,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable); ClassDB::bind_method(D_METHOD("global_menu_set_item_radio_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_radio_checkable); ClassDB::bind_method(D_METHOD("global_menu_set_item_callback", "menu_root", "idx", "callback"), &DisplayServer::global_menu_set_item_callback); + ClassDB::bind_method(D_METHOD("global_menu_set_item_key_callback", "menu_root", "idx", "key_callback"), &DisplayServer::global_menu_set_item_key_callback); ClassDB::bind_method(D_METHOD("global_menu_set_item_tag", "menu_root", "idx", "tag"), &DisplayServer::global_menu_set_item_tag); ClassDB::bind_method(D_METHOD("global_menu_set_item_text", "menu_root", "idx", "text"), &DisplayServer::global_menu_set_item_text); ClassDB::bind_method(D_METHOD("global_menu_set_item_submenu", "menu_root", "idx", "submenu"), &DisplayServer::global_menu_set_item_submenu); @@ -586,6 +597,10 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("tts_set_utterance_callback", "event", "callable"), &DisplayServer::tts_set_utterance_callback); ClassDB::bind_method(D_METHOD("_tts_post_utterance_event", "event", "id", "char_pos"), &DisplayServer::tts_post_utterance_event); + ClassDB::bind_method(D_METHOD("is_dark_mode_supported"), &DisplayServer::is_dark_mode_supported); + ClassDB::bind_method(D_METHOD("is_dark_mode"), &DisplayServer::is_dark_mode); + ClassDB::bind_method(D_METHOD("get_accent_color"), &DisplayServer::get_accent_color); + ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode); ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode); diff --git a/servers/display_server.h b/servers/display_server.h index 0b162fe491..ab4f9fc499 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -128,14 +128,14 @@ public: virtual bool has_feature(Feature p_feature) const = 0; virtual String get_name() const = 0; - virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual int global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual int global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual int global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual int global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); - virtual int global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1); + virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); + virtual int global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1); virtual int global_menu_add_separator(const String &p_menu_root, int p_index = -1); virtual int global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const; @@ -145,6 +145,7 @@ public: virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const; virtual bool global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const; virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx) const; + virtual Callable global_menu_get_item_key_callback(const String &p_menu_root, int p_idx) const; virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx) const; virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx) const; virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const; @@ -160,6 +161,7 @@ public: virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable); virtual void global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable); virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback); + virtual void global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback); virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag); virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text); virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu); @@ -210,6 +212,10 @@ public: virtual void tts_set_utterance_callback(TTSUtteranceEvent p_event, const Callable &p_callable); virtual void tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id, int p_pos = 0); + virtual bool is_dark_mode_supported() const { return false; }; + virtual bool is_dark_mode() const { return false; }; + virtual Color get_accent_color() const { return Color(0, 0, 0, 0); }; + enum MouseMode { MOUSE_MODE_VISIBLE, MOUSE_MODE_HIDDEN, diff --git a/servers/extensions/physics_server_2d_extension.cpp b/servers/extensions/physics_server_2d_extension.cpp new file mode 100644 index 0000000000..36f3be2468 --- /dev/null +++ b/servers/extensions/physics_server_2d_extension.cpp @@ -0,0 +1,338 @@ +/*************************************************************************/ +/* physics_server_2d_extension.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_2d_extension.h" + +bool PhysicsDirectSpaceState2DExtension::is_body_excluded_from_query(const RID &p_body) const { + return exclude && exclude->has(p_body); +} + +thread_local const HashSet<RID> *PhysicsDirectSpaceState2DExtension::exclude = nullptr; + +void PhysicsDirectSpaceState2DExtension::_bind_methods() { + GDVIRTUAL_BIND(_intersect_ray, "from", "to", "collision_mask", "collide_with_bodies", "collide_with_areas", "hit_from_inside", "result"); + GDVIRTUAL_BIND(_intersect_point, "position", "canvas_instance_id", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results"); + GDVIRTUAL_BIND(_intersect_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "result", "max_results"); + GDVIRTUAL_BIND(_cast_motion, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "closest_safe", "closest_unsafe"); + GDVIRTUAL_BIND(_collide_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results", "result_count"); + GDVIRTUAL_BIND(_rest_info, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "rest_info"); +} + +PhysicsDirectSpaceState2DExtension::PhysicsDirectSpaceState2DExtension() { +} + +void PhysicsDirectBodyState2DExtension::_bind_methods() { + GDVIRTUAL_BIND(_get_total_gravity); + GDVIRTUAL_BIND(_get_total_linear_damp); + GDVIRTUAL_BIND(_get_total_angular_damp); + + GDVIRTUAL_BIND(_get_center_of_mass); + GDVIRTUAL_BIND(_get_center_of_mass_local); + GDVIRTUAL_BIND(_get_inverse_mass); + GDVIRTUAL_BIND(_get_inverse_inertia); + + GDVIRTUAL_BIND(_set_linear_velocity, "velocity"); + GDVIRTUAL_BIND(_get_linear_velocity); + + GDVIRTUAL_BIND(_set_angular_velocity, "velocity"); + GDVIRTUAL_BIND(_get_angular_velocity); + + GDVIRTUAL_BIND(_set_transform, "transform"); + GDVIRTUAL_BIND(_get_transform); + + GDVIRTUAL_BIND(_get_velocity_at_local_position, "local_position"); + + GDVIRTUAL_BIND(_apply_central_impulse, "impulse"); + GDVIRTUAL_BIND(_apply_impulse, "impulse", "position"); + GDVIRTUAL_BIND(_apply_torque_impulse, "impulse"); + + GDVIRTUAL_BIND(_apply_central_force, "force"); + GDVIRTUAL_BIND(_apply_force, "force", "position"); + GDVIRTUAL_BIND(_apply_torque, "torque"); + + GDVIRTUAL_BIND(_add_constant_central_force, "force"); + GDVIRTUAL_BIND(_add_constant_force, "force", "position"); + GDVIRTUAL_BIND(_add_constant_torque, "torque"); + + GDVIRTUAL_BIND(_set_constant_force, "force"); + GDVIRTUAL_BIND(_get_constant_force); + + GDVIRTUAL_BIND(_set_constant_torque, "torque"); + GDVIRTUAL_BIND(_get_constant_torque); + + GDVIRTUAL_BIND(_set_sleep_state, "enabled"); + GDVIRTUAL_BIND(_is_sleeping); + + GDVIRTUAL_BIND(_get_contact_count); + + GDVIRTUAL_BIND(_get_contact_local_position, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_local_normal, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_local_shape, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_position, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_id, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_object, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_shape, "contact_idx"); + GDVIRTUAL_BIND(_get_contact_collider_velocity_at_position, "contact_idx"); + + GDVIRTUAL_BIND(_get_step); + GDVIRTUAL_BIND(_integrate_forces); + + GDVIRTUAL_BIND(_get_space_state); +} + +PhysicsDirectBodyState2DExtension::PhysicsDirectBodyState2DExtension() { +} + +thread_local const HashSet<RID> *PhysicsServer2DExtension::exclude_bodies = nullptr; +thread_local const HashSet<ObjectID> *PhysicsServer2DExtension::exclude_objects = nullptr; + +bool PhysicsServer2DExtension::body_test_motion_is_excluding_body(RID p_body) const { + return exclude_bodies && exclude_bodies->has(p_body); +} + +bool PhysicsServer2DExtension::body_test_motion_is_excluding_object(ObjectID p_object) const { + return exclude_objects && exclude_objects->has(p_object); +} + +void PhysicsServer2DExtension::_bind_methods() { + /* SHAPE API */ + + GDVIRTUAL_BIND(_world_boundary_shape_create); + GDVIRTUAL_BIND(_separation_ray_shape_create); + GDVIRTUAL_BIND(_segment_shape_create); + GDVIRTUAL_BIND(_circle_shape_create); + GDVIRTUAL_BIND(_rectangle_shape_create); + GDVIRTUAL_BIND(_capsule_shape_create); + GDVIRTUAL_BIND(_convex_polygon_shape_create); + GDVIRTUAL_BIND(_concave_polygon_shape_create); + + GDVIRTUAL_BIND(_shape_set_data, "shape", "data"); + GDVIRTUAL_BIND(_shape_set_custom_solver_bias, "shape", "bias"); + + GDVIRTUAL_BIND(_shape_get_type, "shape"); + GDVIRTUAL_BIND(_shape_get_data, "shape"); + GDVIRTUAL_BIND(_shape_get_custom_solver_bias, "shape"); + GDVIRTUAL_BIND(_shape_collide, "shape_A", "xform_A", "motion_A", "shape_B", "xform_B", "motion_B", "results", "result_max", "result_count"); + + /* SPACE API */ + + GDVIRTUAL_BIND(_space_create); + GDVIRTUAL_BIND(_space_set_active, "space", "active"); + GDVIRTUAL_BIND(_space_is_active, "space"); + + GDVIRTUAL_BIND(_space_set_param, "space", "param", "value"); + GDVIRTUAL_BIND(_space_get_param, "space", "param"); + + GDVIRTUAL_BIND(_space_get_direct_state, "space"); + + GDVIRTUAL_BIND(_space_set_debug_contacts, "space", "max_contacts"); + GDVIRTUAL_BIND(_space_get_contacts, "space"); + GDVIRTUAL_BIND(_space_get_contact_count, "space"); + + /* AREA API */ + + GDVIRTUAL_BIND(_area_create); + + GDVIRTUAL_BIND(_area_set_space, "area", "space"); + GDVIRTUAL_BIND(_area_get_space, "area"); + + GDVIRTUAL_BIND(_area_add_shape, "area", "shape", "transform", "disabled"); + GDVIRTUAL_BIND(_area_set_shape, "area", "shape_idx", "shape"); + GDVIRTUAL_BIND(_area_set_shape_transform, "area", "shape_idx", "transform"); + GDVIRTUAL_BIND(_area_set_shape_disabled, "area", "shape_idx", "disabled"); + + GDVIRTUAL_BIND(_area_get_shape_count, "area"); + GDVIRTUAL_BIND(_area_get_shape, "area", "shape_idx"); + GDVIRTUAL_BIND(_area_get_shape_transform, "area", "shape_idx"); + + GDVIRTUAL_BIND(_area_remove_shape, "area", "shape_idx"); + GDVIRTUAL_BIND(_area_clear_shapes, "area"); + + GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id"); + GDVIRTUAL_BIND(_area_get_object_instance_id, "area"); + + GDVIRTUAL_BIND(_area_attach_canvas_instance_id, "area", "id"); + GDVIRTUAL_BIND(_area_get_canvas_instance_id, "area"); + + GDVIRTUAL_BIND(_area_set_param, "area", "param", "value"); + GDVIRTUAL_BIND(_area_set_transform, "area", "transform"); + + GDVIRTUAL_BIND(_area_get_param, "area", "param"); + GDVIRTUAL_BIND(_area_get_transform, "area"); + + GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer"); + GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask"); + + GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable"); + GDVIRTUAL_BIND(_area_set_pickable, "area", "pickable"); + + GDVIRTUAL_BIND(_area_set_monitor_callback, "area", "callback"); + GDVIRTUAL_BIND(_area_set_area_monitor_callback, "area", "callback"); + + /* BODY API */ + + GDVIRTUAL_BIND(_body_create); + + GDVIRTUAL_BIND(_body_set_space, "body", "space"); + GDVIRTUAL_BIND(_body_get_space, "body"); + + GDVIRTUAL_BIND(_body_set_mode, "body", "mode"); + GDVIRTUAL_BIND(_body_get_mode, "body"); + + GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled"); + GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape"); + GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform"); + + GDVIRTUAL_BIND(_body_get_shape_count, "body"); + GDVIRTUAL_BIND(_body_get_shape, "body", "shape_idx"); + GDVIRTUAL_BIND(_body_get_shape_transform, "body", "shape_idx"); + + GDVIRTUAL_BIND(_body_set_shape_disabled, "body", "shape_idx", "disabled"); + GDVIRTUAL_BIND(_body_set_shape_as_one_way_collision, "body", "shape_idx", "enable", "margin"); + + GDVIRTUAL_BIND(_body_remove_shape, "body", "shape_idx"); + GDVIRTUAL_BIND(_body_clear_shapes, "body"); + + GDVIRTUAL_BIND(_body_attach_object_instance_id, "body", "id"); + GDVIRTUAL_BIND(_body_get_object_instance_id, "body"); + + GDVIRTUAL_BIND(_body_attach_canvas_instance_id, "body", "id"); + GDVIRTUAL_BIND(_body_get_canvas_instance_id, "body"); + + GDVIRTUAL_BIND(_body_set_continuous_collision_detection_mode, "body", "mode"); + GDVIRTUAL_BIND(_body_get_continuous_collision_detection_mode, "body"); + + GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer"); + GDVIRTUAL_BIND(_body_get_collision_layer, "body"); + + GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask"); + GDVIRTUAL_BIND(_body_get_collision_mask, "body"); + + GDVIRTUAL_BIND(_body_set_collision_priority, "body", "priority"); + GDVIRTUAL_BIND(_body_get_collision_priority, "body"); + + GDVIRTUAL_BIND(_body_set_param, "body", "param", "value"); + GDVIRTUAL_BIND(_body_get_param, "body", "param"); + + GDVIRTUAL_BIND(_body_reset_mass_properties, "body"); + + GDVIRTUAL_BIND(_body_set_state, "body", "state", "value"); + GDVIRTUAL_BIND(_body_get_state, "body", "state"); + + GDVIRTUAL_BIND(_body_apply_central_impulse, "body", "impulse"); + GDVIRTUAL_BIND(_body_apply_torque_impulse, "body", "impulse"); + GDVIRTUAL_BIND(_body_apply_impulse, "body", "impulse", "position"); + + GDVIRTUAL_BIND(_body_apply_central_force, "body", "force"); + GDVIRTUAL_BIND(_body_apply_force, "body", "force", "position"); + GDVIRTUAL_BIND(_body_apply_torque, "body", "torque"); + + GDVIRTUAL_BIND(_body_add_constant_central_force, "body", "force"); + GDVIRTUAL_BIND(_body_add_constant_force, "body", "force", "position"); + GDVIRTUAL_BIND(_body_add_constant_torque, "body", "torque"); + + GDVIRTUAL_BIND(_body_set_constant_force, "body", "force"); + GDVIRTUAL_BIND(_body_get_constant_force, "body"); + + GDVIRTUAL_BIND(_body_set_constant_torque, "body", "torque"); + GDVIRTUAL_BIND(_body_get_constant_torque, "body"); + + GDVIRTUAL_BIND(_body_set_axis_velocity, "body", "axis_velocity"); + + GDVIRTUAL_BIND(_body_add_collision_exception, "body", "excepted_body"); + GDVIRTUAL_BIND(_body_remove_collision_exception, "body", "excepted_body"); + GDVIRTUAL_BIND(_body_get_collision_exceptions, "body"); + + GDVIRTUAL_BIND(_body_set_max_contacts_reported, "body", "amount"); + GDVIRTUAL_BIND(_body_get_max_contacts_reported, "body"); + + GDVIRTUAL_BIND(_body_set_contacts_reported_depth_threshold, "body", "threshold"); + GDVIRTUAL_BIND(_body_get_contacts_reported_depth_threshold, "body"); + + GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable"); + GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body"); + + GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callback"); + GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata"); + + GDVIRTUAL_BIND(_body_collide_shape, "body", "body_shape", "shape", "shape_xform", "motion", "results", "result_max", "result_count"); + + GDVIRTUAL_BIND(_body_set_pickable, "body", "pickable"); + + GDVIRTUAL_BIND(_body_get_direct_state, "body"); + + GDVIRTUAL_BIND(_body_test_motion, "body", "from", "motion", "margin", "collide_separation_ray", "recovery_as_collision", "result"); + + /* JOINT API */ + + GDVIRTUAL_BIND(_joint_create); + GDVIRTUAL_BIND(_joint_clear, "joint"); + + GDVIRTUAL_BIND(_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_joint_disable_collisions_between_bodies, "joint", "disable"); + GDVIRTUAL_BIND(_joint_is_disabled_collisions_between_bodies, "joint"); + + GDVIRTUAL_BIND(_joint_make_pin, "joint", "anchor", "body_a", "body_b"); + GDVIRTUAL_BIND(_joint_make_groove, "joint", "a_groove1", "a_groove2", "b_anchor", "body_a", "body_b"); + GDVIRTUAL_BIND(_joint_make_damped_spring, "joint", "anchor_a", "anchor_b", "body_a", "body_b"); + + GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_damped_spring_joint_set_param, "joint", "param", "value"); + GDVIRTUAL_BIND(_damped_spring_joint_get_param, "joint", "param"); + + GDVIRTUAL_BIND(_joint_get_type, "joint"); + + /* MISC */ + + GDVIRTUAL_BIND(_free_rid, "rid"); + + GDVIRTUAL_BIND(_set_active, "active"); + + GDVIRTUAL_BIND(_init); + GDVIRTUAL_BIND(_step, "step"); + GDVIRTUAL_BIND(_sync); + GDVIRTUAL_BIND(_flush_queries); + GDVIRTUAL_BIND(_end_sync); + GDVIRTUAL_BIND(_finish); + + GDVIRTUAL_BIND(_is_flushing_queries); + GDVIRTUAL_BIND(_get_process_info, "process_info"); +} + +PhysicsServer2DExtension::PhysicsServer2DExtension() { +} + +PhysicsServer2DExtension::~PhysicsServer2DExtension() { +} diff --git a/servers/extensions/physics_server_2d_extension.h b/servers/extensions/physics_server_2d_extension.h new file mode 100644 index 0000000000..3bd3d642c8 --- /dev/null +++ b/servers/extensions/physics_server_2d_extension.h @@ -0,0 +1,462 @@ +/*************************************************************************/ +/* physics_server_2d_extension.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_SERVER_2D_EXTENSION_H +#define PHYSICS_SERVER_2D_EXTENSION_H + +#include "core/extension/ext_wrappers.gen.inc" +#include "core/object/gdvirtual.gen.inc" +#include "core/object/script_language.h" +#include "core/variant/native_ptr.h" +#include "core/variant/type_info.h" +#include "core/variant/typed_array.h" +#include "servers/physics_server_2d.h" + +class PhysicsDirectBodyState2DExtension : public PhysicsDirectBodyState2D { + GDCLASS(PhysicsDirectBodyState2DExtension, PhysicsDirectBodyState2D); + +protected: + static void _bind_methods(); + +public: + // The warning is valid, but unavoidable. If the function is not overridden it will error anyway. + + EXBIND0RC(Vector2, get_total_gravity) + EXBIND0RC(real_t, get_total_angular_damp) + EXBIND0RC(real_t, get_total_linear_damp) + + EXBIND0RC(Vector2, get_center_of_mass) + EXBIND0RC(Vector2, get_center_of_mass_local) + EXBIND0RC(real_t, get_inverse_mass) + EXBIND0RC(real_t, get_inverse_inertia) + + EXBIND1(set_linear_velocity, const Vector2 &) + EXBIND0RC(Vector2, get_linear_velocity) + + EXBIND1(set_angular_velocity, real_t) + EXBIND0RC(real_t, get_angular_velocity) + + EXBIND1(set_transform, const Transform2D &) + EXBIND0RC(Transform2D, get_transform) + + EXBIND1RC(Vector2, get_velocity_at_local_position, const Vector2 &) + + EXBIND1(apply_central_impulse, const Vector2 &) + EXBIND1(apply_torque_impulse, real_t) + EXBIND2(apply_impulse, const Vector2 &, const Vector2 &) + + EXBIND1(apply_central_force, const Vector2 &) + EXBIND2(apply_force, const Vector2 &, const Vector2 &) + EXBIND1(apply_torque, real_t) + + EXBIND1(add_constant_central_force, const Vector2 &) + EXBIND2(add_constant_force, const Vector2 &, const Vector2 &) + EXBIND1(add_constant_torque, real_t) + + EXBIND1(set_constant_force, const Vector2 &) + EXBIND0RC(Vector2, get_constant_force) + + EXBIND1(set_constant_torque, real_t) + EXBIND0RC(real_t, get_constant_torque) + + EXBIND1(set_sleep_state, bool) + EXBIND0RC(bool, is_sleeping) + + EXBIND0RC(int, get_contact_count) + + EXBIND1RC(Vector2, get_contact_local_position, int) + EXBIND1RC(Vector2, get_contact_local_normal, int) + EXBIND1RC(int, get_contact_local_shape, int) + + EXBIND1RC(RID, get_contact_collider, int) + EXBIND1RC(Vector2, get_contact_collider_position, int) + EXBIND1RC(ObjectID, get_contact_collider_id, int) + EXBIND1RC(Object *, get_contact_collider_object, int) + EXBIND1RC(int, get_contact_collider_shape, int) + EXBIND1RC(Vector2, get_contact_collider_velocity_at_position, int) + + EXBIND0RC(real_t, get_step) + EXBIND0(integrate_forces) + + EXBIND0R(PhysicsDirectSpaceState2D *, get_space_state) + + PhysicsDirectBodyState2DExtension(); +}; + +typedef PhysicsDirectSpaceState2D::RayResult PhysicsServer2DExtensionRayResult; +typedef PhysicsDirectSpaceState2D::ShapeResult PhysicsServer2DExtensionShapeResult; +typedef PhysicsDirectSpaceState2D::ShapeRestInfo PhysicsServer2DExtensionShapeRestInfo; + +GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionRayResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionShapeResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionShapeRestInfo) + +class PhysicsDirectSpaceState2DExtension : public PhysicsDirectSpaceState2D { + GDCLASS(PhysicsDirectSpaceState2DExtension, PhysicsDirectSpaceState2D); + + thread_local static const HashSet<RID> *exclude; + +protected: + static void _bind_methods(); + bool is_body_excluded_from_query(const RID &p_body) const; + + GDVIRTUAL7R(bool, _intersect_ray, const Vector2 &, const Vector2 &, uint32_t, bool, bool, bool, GDNativePtr<PhysicsServer2DExtensionRayResult>) + GDVIRTUAL7R(int, _intersect_point, const Vector2 &, ObjectID, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeResult>, int) + GDVIRTUAL9R(int, _intersect_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeResult>, int) + GDVIRTUAL9R(bool, _cast_motion, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<real_t>, GDNativePtr<real_t>) + GDVIRTUAL10R(bool, _collide_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<Vector2>, int, GDNativePtr<int>) + GDVIRTUAL8R(bool, _rest_info, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeRestInfo>) + +public: + virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_intersect_ray, p_parameters.from, p_parameters.to, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, p_parameters.hit_from_inside, &r_result, ret); + exclude = nullptr; + return ret; + } + virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { + exclude = &p_parameters.exclude; + int ret = false; + GDVIRTUAL_REQUIRED_CALL(_intersect_point, p_parameters.position, p_parameters.canvas_instance_id, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret); + exclude = nullptr; + return ret; + } + virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override { + exclude = &p_parameters.exclude; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_intersect_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret); + exclude = nullptr; + return ret; + } + virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_cast_motion, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, &p_closest_safe, &p_closest_unsafe, ret); + exclude = nullptr; + return ret; + } + virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_collide_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, &r_result_count, ret); + exclude = nullptr; + return ret; + } + virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override { + exclude = &p_parameters.exclude; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_rest_info, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_info, ret); + exclude = nullptr; + return ret; + } + + PhysicsDirectSpaceState2DExtension(); +}; + +typedef PhysicsServer2D::MotionResult PhysicsServer2DExtensionMotionResult; + +struct PhysicsServer2DExtensionStateCallback { + void *instance = nullptr; + void (*callback)(void *p_instance, PhysicsDirectBodyState2D *p_state); +}; + +GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionMotionResult) +GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionStateCallback) + +class PhysicsServer2DExtension : public PhysicsServer2D { + GDCLASS(PhysicsServer2DExtension, PhysicsServer2D); + +protected: + static void _bind_methods(); + + GDVIRTUAL9R(bool, _shape_collide, RID, const Transform2D &, const Vector2 &, RID, const Transform2D &, const Vector2 &, GDNativePtr<Vector2>, int, GDNativePtr<int>) + + GDVIRTUAL8R(bool, _body_collide_shape, RID, int, RID, const Transform2D &, const Vector2 &, GDNativePtr<Vector2>, int, GDNativePtr<int>) + +public: + // The warning is valid, but unavoidable. If the function is not overridden it will error anyway. + + /* SHAPE API */ + + EXBIND0R(RID, world_boundary_shape_create) + EXBIND0R(RID, separation_ray_shape_create) + EXBIND0R(RID, segment_shape_create) + EXBIND0R(RID, circle_shape_create) + EXBIND0R(RID, rectangle_shape_create) + EXBIND0R(RID, capsule_shape_create) + EXBIND0R(RID, convex_polygon_shape_create) + EXBIND0R(RID, concave_polygon_shape_create) + + EXBIND2(shape_set_data, RID, const Variant &) + EXBIND2(shape_set_custom_solver_bias, RID, real_t) + + EXBIND1RC(ShapeType, shape_get_type, RID) + EXBIND1RC(Variant, shape_get_data, RID) + EXBIND1RC(real_t, shape_get_custom_solver_bias, RID) + + virtual bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override { + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_shape_collide, p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, &r_result_count, ret); + return ret; + } + + /* SPACE API */ + + EXBIND0R(RID, space_create) + EXBIND2(space_set_active, RID, bool) + EXBIND1RC(bool, space_is_active, RID) + + EXBIND3(space_set_param, RID, SpaceParameter, real_t) + EXBIND2RC(real_t, space_get_param, RID, SpaceParameter) + + EXBIND1R(PhysicsDirectSpaceState2D *, space_get_direct_state, RID) + + EXBIND2(space_set_debug_contacts, RID, int) + EXBIND1RC(Vector<Vector2>, space_get_contacts, RID) + EXBIND1RC(int, space_get_contact_count, RID) + + /* AREA API */ + + //EXBIND0RID(area); + EXBIND0R(RID, area_create) + + EXBIND2(area_set_space, RID, RID) + EXBIND1RC(RID, area_get_space, RID) + + EXBIND4(area_add_shape, RID, RID, const Transform2D &, bool) + EXBIND3(area_set_shape, RID, int, RID) + EXBIND3(area_set_shape_transform, RID, int, const Transform2D &) + EXBIND3(area_set_shape_disabled, RID, int, bool) + + EXBIND1RC(int, area_get_shape_count, RID) + EXBIND2RC(RID, area_get_shape, RID, int) + EXBIND2RC(Transform2D, area_get_shape_transform, RID, int) + + EXBIND2(area_remove_shape, RID, int) + EXBIND1(area_clear_shapes, RID) + + EXBIND2(area_attach_object_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, area_get_object_instance_id, RID) + + EXBIND2(area_attach_canvas_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, area_get_canvas_instance_id, RID) + + EXBIND3(area_set_param, RID, AreaParameter, const Variant &) + EXBIND2(area_set_transform, RID, const Transform2D &) + + EXBIND2RC(Variant, area_get_param, RID, AreaParameter) + EXBIND1RC(Transform2D, area_get_transform, RID) + + EXBIND2(area_set_collision_mask, RID, uint32_t) + EXBIND2(area_set_collision_layer, RID, uint32_t) + + EXBIND2(area_set_monitorable, RID, bool) + EXBIND2(area_set_pickable, RID, bool) + + EXBIND2(area_set_monitor_callback, RID, const Callable &) + EXBIND2(area_set_area_monitor_callback, RID, const Callable &) + + /* BODY API */ + + //EXBIND2RID(body,BodyMode,bool); + EXBIND0R(RID, body_create) + + EXBIND2(body_set_space, RID, RID) + EXBIND1RC(RID, body_get_space, RID) + + EXBIND2(body_set_mode, RID, BodyMode) + EXBIND1RC(BodyMode, body_get_mode, RID) + + EXBIND4(body_add_shape, RID, RID, const Transform2D &, bool) + EXBIND3(body_set_shape, RID, int, RID) + EXBIND3(body_set_shape_transform, RID, int, const Transform2D &) + + EXBIND1RC(int, body_get_shape_count, RID) + EXBIND2RC(RID, body_get_shape, RID, int) + EXBIND2RC(Transform2D, body_get_shape_transform, RID, int) + + EXBIND3(body_set_shape_disabled, RID, int, bool) + EXBIND4(body_set_shape_as_one_way_collision, RID, int, bool, real_t) + + EXBIND2(body_remove_shape, RID, int) + EXBIND1(body_clear_shapes, RID) + + EXBIND2(body_attach_object_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, body_get_object_instance_id, RID) + + EXBIND2(body_attach_canvas_instance_id, RID, ObjectID) + EXBIND1RC(ObjectID, body_get_canvas_instance_id, RID) + + EXBIND2(body_set_continuous_collision_detection_mode, RID, CCDMode) + EXBIND1RC(CCDMode, body_get_continuous_collision_detection_mode, RID) + + EXBIND2(body_set_collision_layer, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_collision_layer, RID) + + EXBIND2(body_set_collision_mask, RID, uint32_t) + EXBIND1RC(uint32_t, body_get_collision_mask, RID) + + EXBIND2(body_set_collision_priority, RID, real_t) + EXBIND1RC(real_t, body_get_collision_priority, RID) + + EXBIND3(body_set_param, RID, BodyParameter, const Variant &) + EXBIND2RC(Variant, body_get_param, RID, BodyParameter) + + EXBIND1(body_reset_mass_properties, RID) + + EXBIND3(body_set_state, RID, BodyState, const Variant &) + EXBIND2RC(Variant, body_get_state, RID, BodyState) + + EXBIND2(body_apply_central_impulse, RID, const Vector2 &) + EXBIND2(body_apply_torque_impulse, RID, real_t) + EXBIND3(body_apply_impulse, RID, const Vector2 &, const Vector2 &) + + EXBIND2(body_apply_central_force, RID, const Vector2 &) + EXBIND3(body_apply_force, RID, const Vector2 &, const Vector2 &) + EXBIND2(body_apply_torque, RID, real_t) + + EXBIND2(body_add_constant_central_force, RID, const Vector2 &) + EXBIND3(body_add_constant_force, RID, const Vector2 &, const Vector2 &) + EXBIND2(body_add_constant_torque, RID, real_t) + + EXBIND2(body_set_constant_force, RID, const Vector2 &) + EXBIND1RC(Vector2, body_get_constant_force, RID) + + EXBIND2(body_set_constant_torque, RID, real_t) + EXBIND1RC(real_t, body_get_constant_torque, RID) + + EXBIND2(body_set_axis_velocity, RID, const Vector2 &) + + EXBIND2(body_add_collision_exception, RID, RID) + EXBIND2(body_remove_collision_exception, RID, RID) + GDVIRTUAL1RC(TypedArray<RID>, _body_get_collision_exceptions, RID) + + void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override { + TypedArray<RID> ret; + GDVIRTUAL_REQUIRED_CALL(_body_get_collision_exceptions, p_body, ret); + for (int i = 0; i < ret.size(); i++) { + p_exceptions->push_back(ret[i]); + } + } + + EXBIND2(body_set_max_contacts_reported, RID, int) + EXBIND1RC(int, body_get_max_contacts_reported, RID) + + EXBIND2(body_set_contacts_reported_depth_threshold, RID, real_t) + EXBIND1RC(real_t, body_get_contacts_reported_depth_threshold, RID) + + EXBIND2(body_set_omit_force_integration, RID, bool) + EXBIND1RC(bool, body_is_omitting_force_integration, RID) + + GDVIRTUAL2(_body_set_state_sync_callback, RID, GDNativePtr<PhysicsServer2DExtensionStateCallback>) + void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override { + PhysicsServer2DExtensionStateCallback callback; + callback.callback = p_callback; + callback.instance = p_instance; + GDVIRTUAL_REQUIRED_CALL(_body_set_state_sync_callback, p_body, &callback); + } + EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &) + + virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override { + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_body_collide_shape, p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, &r_result_count, ret); + return ret; + } + + EXBIND2(body_set_pickable, RID, bool) + + EXBIND1R(PhysicsDirectBodyState2D *, body_get_direct_state, RID) + + GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform2D &, const Vector2 &, real_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionMotionResult>) + + thread_local static const HashSet<RID> *exclude_bodies; + thread_local static const HashSet<ObjectID> *exclude_objects; + + bool body_test_motion_is_excluding_body(RID p_body) const; + bool body_test_motion_is_excluding_object(ObjectID p_object) const; + + bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override { + bool ret = false; + exclude_bodies = &p_parameters.exclude_bodies; + exclude_objects = &p_parameters.exclude_objects; + GDVIRTUAL_REQUIRED_CALL(_body_test_motion, p_body, p_parameters.from, p_parameters.motion, p_parameters.margin, p_parameters.collide_separation_ray, p_parameters.recovery_as_collision, r_result, ret); + exclude_bodies = nullptr; + exclude_objects = nullptr; + return ret; + } + + /* JOINT API */ + + EXBIND0R(RID, joint_create) + EXBIND1(joint_clear, RID) + + EXBIND3(joint_set_param, RID, JointParam, real_t) + EXBIND2RC(real_t, joint_get_param, RID, JointParam) + + EXBIND2(joint_disable_collisions_between_bodies, RID, bool) + EXBIND1RC(bool, joint_is_disabled_collisions_between_bodies, RID) + + EXBIND4(joint_make_pin, RID, const Vector2 &, RID, RID) + EXBIND6(joint_make_groove, RID, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID) + EXBIND5(joint_make_damped_spring, RID, const Vector2 &, const Vector2 &, RID, RID) + + EXBIND3(pin_joint_set_param, RID, PinJointParam, real_t) + EXBIND2RC(real_t, pin_joint_get_param, RID, PinJointParam) + + EXBIND3(damped_spring_joint_set_param, RID, DampedSpringParam, real_t) + EXBIND2RC(real_t, damped_spring_joint_get_param, RID, DampedSpringParam) + + EXBIND1RC(JointType, joint_get_type, RID) + + /* MISC */ + + GDVIRTUAL1(_free_rid, RID) + virtual void free(RID p_rid) override { + GDVIRTUAL_REQUIRED_CALL(_free_rid, p_rid); + } + + EXBIND1(set_active, bool) + + EXBIND0(init) + EXBIND1(step, real_t) + EXBIND0(sync) + EXBIND0(flush_queries) + EXBIND0(end_sync) + EXBIND0(finish) + + EXBIND0RC(bool, is_flushing_queries) + EXBIND1R(int, get_process_info, ProcessInfo) + + PhysicsServer2DExtension(); + ~PhysicsServer2DExtension(); +}; + +#endif // PHYSICS_SERVER_2D_EXTENSION_H diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp index 7d797bf611..800284dc60 100644 --- a/servers/extensions/physics_server_3d_extension.cpp +++ b/servers/extensions/physics_server_3d_extension.cpp @@ -125,6 +125,8 @@ bool PhysicsServer3DExtension::body_test_motion_is_excluding_object(ObjectID p_o } void PhysicsServer3DExtension::_bind_methods() { + /* SHAPE API */ + GDVIRTUAL_BIND(_world_boundary_shape_create); GDVIRTUAL_BIND(_separation_ray_shape_create); GDVIRTUAL_BIND(_sphere_shape_create); @@ -137,18 +139,34 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_custom_shape_create); GDVIRTUAL_BIND(_shape_set_data, "shape", "data"); + GDVIRTUAL_BIND(_shape_set_custom_solver_bias, "shape", "bias"); + + GDVIRTUAL_BIND(_shape_set_margin, "shape", "margin"); + GDVIRTUAL_BIND(_shape_get_margin, "shape"); GDVIRTUAL_BIND(_shape_get_type, "shape"); GDVIRTUAL_BIND(_shape_get_data, "shape"); + GDVIRTUAL_BIND(_shape_get_custom_solver_bias, "shape"); + + /* SPACE API */ GDVIRTUAL_BIND(_space_create); GDVIRTUAL_BIND(_space_set_active, "space", "active"); GDVIRTUAL_BIND(_space_is_active, "space"); + GDVIRTUAL_BIND(_space_set_param, "space", "param", "value"); GDVIRTUAL_BIND(_space_get_param, "space", "param"); + GDVIRTUAL_BIND(_space_get_direct_state, "space"); + GDVIRTUAL_BIND(_space_set_debug_contacts, "space", "max_contacts"); + GDVIRTUAL_BIND(_space_get_contacts, "space"); + GDVIRTUAL_BIND(_space_get_contact_count, "space"); + + /* AREA API */ + GDVIRTUAL_BIND(_area_create); + GDVIRTUAL_BIND(_area_set_space, "area", "space"); GDVIRTUAL_BIND(_area_get_space, "area"); @@ -164,8 +182,8 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_area_remove_shape, "area", "shape_idx"); GDVIRTUAL_BIND(_area_clear_shapes, "area"); - GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer"); - GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask"); + GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id"); + GDVIRTUAL_BIND(_area_get_object_instance_id, "area"); GDVIRTUAL_BIND(_area_set_param, "area", "param", "value"); GDVIRTUAL_BIND(_area_set_transform, "area", "transform"); @@ -173,14 +191,16 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_area_get_param, "area", "param"); GDVIRTUAL_BIND(_area_get_transform, "area"); - GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id"); - GDVIRTUAL_BIND(_area_get_object_instance_id, "area"); + GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer"); + GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask"); + + GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable"); + GDVIRTUAL_BIND(_area_set_ray_pickable, "area", "enable"); GDVIRTUAL_BIND(_area_set_monitor_callback, "area", "callback"); GDVIRTUAL_BIND(_area_set_area_monitor_callback, "area", "callback"); - GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable"); - GDVIRTUAL_BIND(_area_set_ray_pickable, "area", "enable"); + /* BODY API */ GDVIRTUAL_BIND(_body_create); @@ -190,15 +210,6 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_body_set_mode, "body", "mode"); GDVIRTUAL_BIND(_body_get_mode, "body"); - GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer"); - GDVIRTUAL_BIND(_body_get_collision_layer, "body"); - - GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask"); - GDVIRTUAL_BIND(_body_get_collision_mask, "body"); - - GDVIRTUAL_BIND(_body_set_collision_priority, "body", "priority"); - GDVIRTUAL_BIND(_body_get_collision_priority, "body"); - GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled"); GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape"); GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform"); @@ -217,6 +228,18 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_body_set_enable_continuous_collision_detection, "body", "enable"); GDVIRTUAL_BIND(_body_is_continuous_collision_detection_enabled, "body"); + GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer"); + GDVIRTUAL_BIND(_body_get_collision_layer, "body"); + + GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask"); + GDVIRTUAL_BIND(_body_get_collision_mask, "body"); + + GDVIRTUAL_BIND(_body_set_collision_priority, "body", "priority"); + GDVIRTUAL_BIND(_body_get_collision_priority, "body"); + + GDVIRTUAL_BIND(_body_set_user_flags, "body", "flags"); + GDVIRTUAL_BIND(_body_get_user_flags, "body"); + GDVIRTUAL_BIND(_body_set_param, "body", "param", "value"); GDVIRTUAL_BIND(_body_get_param, "body", "param"); @@ -250,13 +273,18 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_body_add_collision_exception, "body", "excepted_body"); GDVIRTUAL_BIND(_body_remove_collision_exception, "body", "excepted_body"); + GDVIRTUAL_BIND(_body_get_collision_exceptions, "body"); GDVIRTUAL_BIND(_body_set_max_contacts_reported, "body", "amount"); GDVIRTUAL_BIND(_body_get_max_contacts_reported, "body"); + GDVIRTUAL_BIND(_body_set_contacts_reported_depth_threshold, "body", "threshold"); + GDVIRTUAL_BIND(_body_get_contacts_reported_depth_threshold, "body"); + GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable"); GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body"); + GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callback"); GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata"); GDVIRTUAL_BIND(_body_set_ray_pickable, "body", "enable"); @@ -265,12 +293,68 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_body_get_direct_state, "body"); + /* SOFT BODY API */ + + GDVIRTUAL_BIND(_soft_body_create); + + GDVIRTUAL_BIND(_soft_body_update_rendering_server, "body", "rendering_server_handler"); + + GDVIRTUAL_BIND(_soft_body_set_space, "body", "space"); + GDVIRTUAL_BIND(_soft_body_get_space, "body"); + + GDVIRTUAL_BIND(_soft_body_set_ray_pickable, "body", "enable"); + + GDVIRTUAL_BIND(_soft_body_set_collision_layer, "body", "layer"); + GDVIRTUAL_BIND(_soft_body_get_collision_layer, "body"); + + GDVIRTUAL_BIND(_soft_body_set_collision_mask, "body", "mask"); + GDVIRTUAL_BIND(_soft_body_get_collision_mask, "body"); + + GDVIRTUAL_BIND(_soft_body_add_collision_exception, "body", "body_b"); + GDVIRTUAL_BIND(_soft_body_remove_collision_exception, "body", "body_b"); + GDVIRTUAL_BIND(_soft_body_get_collision_exceptions, "body"); + + GDVIRTUAL_BIND(_soft_body_set_state, "body", "state", "variant"); + GDVIRTUAL_BIND(_soft_body_get_state, "body", "state"); + + GDVIRTUAL_BIND(_soft_body_set_transform, "body", "transform"); + + GDVIRTUAL_BIND(_soft_body_set_simulation_precision, "body", "simulation_precision"); + GDVIRTUAL_BIND(_soft_body_get_simulation_precision, "body"); + + GDVIRTUAL_BIND(_soft_body_set_total_mass, "body", "total_mass"); + GDVIRTUAL_BIND(_soft_body_get_total_mass, "body"); + + GDVIRTUAL_BIND(_soft_body_set_linear_stiffness, "body", "linear_stiffness"); + GDVIRTUAL_BIND(_soft_body_get_linear_stiffness, "body"); + + GDVIRTUAL_BIND(_soft_body_set_pressure_coefficient, "body", "pressure_coefficient"); + GDVIRTUAL_BIND(_soft_body_get_pressure_coefficient, "body"); + + GDVIRTUAL_BIND(_soft_body_set_damping_coefficient, "body", "damping_coefficient"); + GDVIRTUAL_BIND(_soft_body_get_damping_coefficient, "body"); + + GDVIRTUAL_BIND(_soft_body_set_drag_coefficient, "body", "drag_coefficient"); + GDVIRTUAL_BIND(_soft_body_get_drag_coefficient, "body"); + + GDVIRTUAL_BIND(_soft_body_set_mesh, "body", "mesh"); + GDVIRTUAL_BIND(_soft_body_get_bounds, "body"); + GDVIRTUAL_BIND(_soft_body_move_point, "body", "point_index", "global_position"); + GDVIRTUAL_BIND(_soft_body_get_point_global_position, "body", "point_index"); + + GDVIRTUAL_BIND(_soft_body_remove_all_pinned_points, "body"); + GDVIRTUAL_BIND(_soft_body_pin_point, "body", "point_index", "pin"); + GDVIRTUAL_BIND(_soft_body_is_point_pinned, "body", "point_index"); + + /* JOINT API */ + GDVIRTUAL_BIND(_joint_create); GDVIRTUAL_BIND(_joint_clear, "joint"); GDVIRTUAL_BIND(_joint_make_pin, "joint", "body_A", "local_A", "body_B", "local_B"); + GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value"); GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param"); @@ -281,6 +365,7 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_pin_joint_get_local_b, "joint"); GDVIRTUAL_BIND(_joint_make_hinge, "joint", "body_A", "hinge_A", "body_B", "hinge_B"); + GDVIRTUAL_BIND(_joint_make_hinge_simple, "joint", "body_A", "pivot_A", "axis_A", "body_B", "pivot_B", "axis_B"); GDVIRTUAL_BIND(_hinge_joint_set_param, "joint", "param", "value"); GDVIRTUAL_BIND(_hinge_joint_get_param, "joint", "param"); @@ -298,11 +383,6 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_cone_twist_joint_set_param, "joint", "param", "value"); GDVIRTUAL_BIND(_cone_twist_joint_get_param, "joint", "param"); - GDVIRTUAL_BIND(_joint_get_type, "joint"); - - GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority"); - GDVIRTUAL_BIND(_joint_get_solver_priority, "joint"); - GDVIRTUAL_BIND(_joint_make_generic_6dof, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B"); GDVIRTUAL_BIND(_generic_6dof_joint_set_param, "joint", "axis", "param", "value"); @@ -311,10 +391,23 @@ void PhysicsServer3DExtension::_bind_methods() { GDVIRTUAL_BIND(_generic_6dof_joint_set_flag, "joint", "axis", "flag", "enable"); GDVIRTUAL_BIND(_generic_6dof_joint_get_flag, "joint", "axis", "flag"); + GDVIRTUAL_BIND(_joint_get_type, "joint"); + + GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority"); + GDVIRTUAL_BIND(_joint_get_solver_priority, "joint"); + GDVIRTUAL_BIND(_free_rid, "rid"); GDVIRTUAL_BIND(_set_active, "active"); + GDVIRTUAL_BIND(_init); + GDVIRTUAL_BIND(_step, "step"); + GDVIRTUAL_BIND(_sync); + GDVIRTUAL_BIND(_flush_queries); + GDVIRTUAL_BIND(_end_sync); + GDVIRTUAL_BIND(_finish); + + GDVIRTUAL_BIND(_is_flushing_queries); GDVIRTUAL_BIND(_get_process_info, "process_info"); } diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h index 3200438253..b6ed346a3d 100644 --- a/servers/extensions/physics_server_3d_extension.h +++ b/servers/extensions/physics_server_3d_extension.h @@ -210,6 +210,8 @@ protected: public: // The warning is valid, but unavoidable. If the function is not overridden it will error anyway. + /* SHAPE API */ + EXBIND0R(RID, world_boundary_shape_create) EXBIND0R(RID, separation_ray_shape_create) EXBIND0R(RID, sphere_shape_create) @@ -262,6 +264,7 @@ public: EXBIND1RC(int, area_get_shape_count, RID) EXBIND2RC(RID, area_get_shape, RID, int) EXBIND2RC(Transform3D, area_get_shape_transform, RID, int) + EXBIND2(area_remove_shape, RID, int) EXBIND1(area_clear_shapes, RID) @@ -297,12 +300,11 @@ public: EXBIND4(body_add_shape, RID, RID, const Transform3D &, bool) EXBIND3(body_set_shape, RID, int, RID) EXBIND3(body_set_shape_transform, RID, int, const Transform3D &) + EXBIND3(body_set_shape_disabled, RID, int, bool) EXBIND1RC(int, body_get_shape_count, RID) - EXBIND2RC(Transform3D, body_get_shape_transform, RID, int) EXBIND2RC(RID, body_get_shape, RID, int) - - EXBIND3(body_set_shape_disabled, RID, int, bool) + EXBIND2RC(Transform3D, body_get_shape_transform, RID, int) EXBIND2(body_remove_shape, RID, int) EXBIND1(body_clear_shapes, RID) @@ -333,9 +335,9 @@ public: EXBIND3(body_set_state, RID, BodyState, const Variant &) EXBIND2RC(Variant, body_get_state, RID, BodyState) - EXBIND2(body_apply_torque_impulse, RID, const Vector3 &) EXBIND2(body_apply_central_impulse, RID, const Vector3 &) EXBIND3(body_apply_impulse, RID, const Vector3 &, const Vector3 &) + EXBIND2(body_apply_torque_impulse, RID, const Vector3 &) EXBIND2(body_apply_central_force, RID, const Vector3 &) EXBIND3(body_apply_force, RID, const Vector3 &, const Vector3 &) @@ -476,7 +478,6 @@ public: /* JOINT API */ EXBIND0R(RID, joint_create) - EXBIND1(joint_clear, RID) EXBIND5(joint_make_pin, RID, RID, const Vector3 &, RID, const Vector3 &) @@ -537,8 +538,8 @@ public: EXBIND0(init) EXBIND1(step, real_t) EXBIND0(sync) - EXBIND0(end_sync) EXBIND0(flush_queries) + EXBIND0(end_sync) EXBIND0(finish) EXBIND0RC(bool, is_flushing_queries) diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 0f73df8894..cec8b95225 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -53,6 +53,12 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr; return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0)); \ } +#define FORWARD_1_R_C(CONV_R, FUNC_NAME, T_0, D_0, CONV_0) \ + NavigationServer2D::FUNC_NAME(T_0 D_0) \ + const { \ + return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0))); \ + } + #define FORWARD_2_C(FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \ NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1) \ const { \ @@ -190,6 +196,22 @@ Color NavigationServer2D::get_debug_navigation_geometry_face_disabled_color() co return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color(); } +void NavigationServer2D::set_debug_navigation_link_connection_color(const Color &p_color) { + NavigationServer3D::get_singleton_mut()->set_debug_navigation_link_connection_color(p_color); +} + +Color NavigationServer2D::get_debug_navigation_link_connection_color() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_color(); +} + +void NavigationServer2D::set_debug_navigation_link_connection_disabled_color(const Color &p_color) { + NavigationServer3D::get_singleton_mut()->set_debug_navigation_link_connection_disabled_color(p_color); +} + +Color NavigationServer2D::get_debug_navigation_link_connection_disabled_color() const { + return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_disabled_color(); +} + void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool p_value) { NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections(p_value); } @@ -209,10 +231,13 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin); + ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer2D::map_set_link_connection_radius); + ClassDB::bind_method(D_METHOD("map_get_link_connection_radius", "map"), &NavigationServer2D::map_get_link_connection_radius); ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer2D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner); + ClassDB::bind_method(D_METHOD("map_get_links", "map"), &NavigationServer2D::map_get_links); ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer2D::map_get_regions); ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer2D::map_get_agents); @@ -234,6 +259,22 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end); + ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer2D::link_create); + ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer2D::link_set_map); + ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer2D::link_get_map); + ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer2D::link_set_bidirectional); + 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_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); + ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer2D::link_get_travel_cost); + ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map); @@ -265,6 +306,8 @@ NavigationServer2D::~NavigationServer2D() { TypedArray<RID> FORWARD_0_C(get_maps); +TypedArray<RID> FORWARD_1_C(map_get_links, RID, p_map, rid_to_rid); + TypedArray<RID> FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid); TypedArray<RID> FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid); @@ -289,6 +332,9 @@ real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid); void FORWARD_2_C(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real); real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid); +void FORWARD_2_C(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius, rid_to_rid, real_to_real); +real_t FORWARD_1_C(map_get_link_connection_radius, RID, p_map, rid_to_rid); + Vector<Vector2> FORWARD_5_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, uint32_t, p_layers, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool, uint32_to_uint32); Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); @@ -315,6 +361,23 @@ int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid); Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int); Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int); +RID FORWARD_0_C(link_create); + +void FORWARD_2_C(link_set_map, RID, p_link, RID, p_map, rid_to_rid, rid_to_rid); +RID FORWARD_1_C(link_get_map, RID, p_link, rid_to_rid); +void FORWARD_2_C(link_set_bidirectional, RID, p_link, bool, p_bidirectional, rid_to_rid, bool_to_bool); +bool FORWARD_1_C(link_is_bidirectional, RID, p_link, rid_to_rid); +void FORWARD_2_C(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_C(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_C(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_C(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_C(link_set_travel_cost, RID, p_link, real_t, p_travel_cost, rid_to_rid, real_to_real); +real_t FORWARD_1_C(link_get_travel_cost, RID, p_link, rid_to_rid); + RID NavigationServer2D::agent_create() const { RID agent = NavigationServer3D::get_singleton()->agent_create(); NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 5e96466d66..b2ea4c28a0 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -76,12 +76,19 @@ public: /// Returns the edge connection margin of this map. virtual real_t map_get_edge_connection_margin(RID p_map) const; + /// Set the map link connection radius used to attach links to the nav mesh. + virtual void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) const; + + /// Returns the link connection radius of this map. + virtual real_t map_get_link_connection_radius(RID p_map) const; + /// Returns the navigation path to reach the destination from the origin. virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const; virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; + virtual TypedArray<RID> map_get_links(RID p_map) const; virtual TypedArray<RID> map_get_regions(RID p_map) const; virtual TypedArray<RID> map_get_agents(RID p_map) const; @@ -119,6 +126,37 @@ 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. + virtual RID link_create() const; + + /// Set the map of this link. + virtual void link_set_map(RID p_link, RID p_map) const; + virtual RID link_get_map(RID p_link) const; + + /// Set whether this link travels in both directions. + virtual void link_set_bidirectional(RID p_link, bool p_bidirectional) const; + virtual bool link_is_bidirectional(RID p_link) const; + + /// Set the link's layers. + virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) const; + 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) const; + virtual Vector2 link_get_start_location(RID p_link) const; + + /// Set the end location of the link. + virtual void link_set_end_location(RID p_link, Vector2 p_location) const; + virtual Vector2 link_get_end_location(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) const; + virtual real_t link_get_enter_cost(RID p_link) const; + + /// Set the travel cost of the link. + virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const; + virtual real_t link_get_travel_cost(RID p_link) const; + /// Creates the agent. virtual RID agent_create() const; @@ -198,6 +236,12 @@ public: void set_debug_navigation_geometry_face_disabled_color(const Color &p_color); Color get_debug_navigation_geometry_face_disabled_color() const; + void set_debug_navigation_link_connection_color(const Color &p_color); + Color get_debug_navigation_link_connection_color() const; + + 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_enable_edge_connections(const bool p_value); bool get_debug_navigation_enable_edge_connections() const; #endif // DEBUG_ENABLED diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 466b74bc64..bc0602e1df 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -48,12 +48,15 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin); + ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer3D::map_set_link_connection_radius); + ClassDB::bind_method(D_METHOD("map_get_link_connection_radius", "map"), &NavigationServer3D::map_get_link_connection_radius); ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer3D::map_get_path, DEFVAL(1)); ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false)); ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point); ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal); ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner); + ClassDB::bind_method(D_METHOD("map_get_links", "map"), &NavigationServer3D::map_get_links); ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer3D::map_get_regions); ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer3D::map_get_agents); @@ -76,6 +79,22 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end); + ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer3D::link_create); + ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer3D::link_set_map); + ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer3D::link_get_map); + ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer3D::link_set_bidirectional); + 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_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); + ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer3D::link_get_travel_cost); + ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create); ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map); ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map); @@ -118,11 +137,16 @@ NavigationServer3D::NavigationServer3D() { debug_navigation_geometry_face_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_color", Color(0.5, 1.0, 1.0, 0.4)); debug_navigation_geometry_edge_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_disabled_color", Color(0.5, 0.5, 0.5, 1.0)); 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_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); debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines", true); debug_navigation_enable_edge_lines_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines_xray", true); debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/enable_geometry_face_random_color", true); + 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); if (Engine::get_singleton()->is_editor_hint()) { // enable NavigationServer3D when in Editor or else navmesh edge connections are invisible @@ -261,6 +285,40 @@ Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_edge_connection return debug_navigation_edge_connections_material; } +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connections_material() { + if (debug_navigation_link_connections_material.is_valid()) { + return debug_navigation_link_connections_material; + } + + Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + material->set_albedo(debug_navigation_link_connection_color); + if (debug_navigation_enable_link_connections_xray) { + material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + } + material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2); + + debug_navigation_link_connections_material = material; + return debug_navigation_link_connections_material; +} + +Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connections_disabled_material() { + if (debug_navigation_link_connections_disabled_material.is_valid()) { + return debug_navigation_link_connections_disabled_material; + } + + Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D)); + material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); + material->set_albedo(debug_navigation_link_connection_disabled_color); + if (debug_navigation_enable_link_connections_xray) { + material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); + } + material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2); + + debug_navigation_link_connections_disabled_material = material; + return debug_navigation_link_connections_disabled_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()) { @@ -316,6 +374,28 @@ Color NavigationServer3D::get_debug_navigation_geometry_face_disabled_color() co return debug_navigation_geometry_face_disabled_color; } +void NavigationServer3D::set_debug_navigation_link_connection_color(const Color &p_color) { + debug_navigation_link_connection_color = p_color; + if (debug_navigation_link_connections_material.is_valid()) { + debug_navigation_link_connections_material->set_albedo(debug_navigation_link_connection_color); + } +} + +Color NavigationServer3D::get_debug_navigation_link_connection_color() const { + return debug_navigation_link_connection_color; +} + +void NavigationServer3D::set_debug_navigation_link_connection_disabled_color(const Color &p_color) { + debug_navigation_link_connection_disabled_color = p_color; + if (debug_navigation_link_connections_disabled_material.is_valid()) { + debug_navigation_link_connections_disabled_material->set_albedo(debug_navigation_link_connection_disabled_color); + } +} + +Color NavigationServer3D::get_debug_navigation_link_connection_disabled_color() const { + return debug_navigation_link_connection_disabled_color; +} + void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) { debug_navigation_enable_edge_connections = p_value; debug_dirty = true; @@ -368,6 +448,27 @@ bool NavigationServer3D::get_debug_navigation_enable_geometry_face_random_color( return debug_navigation_enable_geometry_face_random_color; } +void NavigationServer3D::set_debug_navigation_enable_link_connections(const bool p_value) { + debug_navigation_enable_link_connections = p_value; + debug_dirty = true; + call_deferred("_emit_navigation_debug_changed_signal"); +} + +bool NavigationServer3D::get_debug_navigation_enable_link_connections() const { + return debug_navigation_enable_link_connections; +} + +void NavigationServer3D::set_debug_navigation_enable_link_connections_xray(const bool p_value) { + debug_navigation_enable_link_connections_xray = p_value; + if (debug_navigation_link_connections_material.is_valid()) { + debug_navigation_link_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_link_connections_xray); + } +} + +bool NavigationServer3D::get_debug_navigation_enable_link_connections_xray() const { + return debug_navigation_enable_link_connections_xray; +} + void NavigationServer3D::set_debug_enabled(bool p_enabled) { if (debug_enabled != p_enabled) { debug_dirty = true; diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 3213da3d84..02770794c6 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -85,6 +85,12 @@ public: /// Returns the edge connection margin of this map. virtual real_t map_get_edge_connection_margin(RID p_map) const = 0; + /// Set the map link connection radius used to attach links to the nav mesh. + virtual void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) const = 0; + + /// Returns the link connection radius of this map. + virtual real_t map_get_link_connection_radius(RID p_map) const = 0; + /// Returns the navigation path to reach the destination from the origin. virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const = 0; @@ -93,6 +99,7 @@ public: virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0; virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0; + virtual TypedArray<RID> map_get_links(RID p_map) const = 0; virtual TypedArray<RID> map_get_regions(RID p_map) const = 0; virtual TypedArray<RID> map_get_agents(RID p_map) const = 0; @@ -133,6 +140,37 @@ 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. + virtual RID link_create() const = 0; + + /// Set the map of this link. + virtual void link_set_map(RID p_link, RID p_map) const = 0; + virtual RID link_get_map(RID p_link) const = 0; + + /// Set whether this link travels in both directions. + virtual void link_set_bidirectional(RID p_link, bool p_bidirectional) const = 0; + virtual bool link_is_bidirectional(RID p_link) const = 0; + + /// Set the link's layers. + virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) const = 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) const = 0; + virtual Vector3 link_get_start_location(RID p_link) const = 0; + + /// Set the end location of the link. + virtual void link_set_end_location(RID p_link, Vector3 p_location) const = 0; + virtual Vector3 link_get_end_location(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) const = 0; + virtual real_t link_get_enter_cost(RID p_link) const = 0; + + /// Set the travel cost of the link. + virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const = 0; + virtual real_t link_get_travel_cost(RID p_link) const = 0; + /// Creates the agent. virtual RID agent_create() const = 0; @@ -209,29 +247,38 @@ public: virtual ~NavigationServer3D(); #ifdef DEBUG_ENABLED +private: bool debug_enabled = false; bool debug_dirty = true; void _emit_navigation_debug_changed_signal(); - void set_debug_enabled(bool p_enabled); - bool get_debug_enabled() const; - Color debug_navigation_edge_connection_color = Color(1.0, 0.0, 1.0, 1.0); Color debug_navigation_geometry_edge_color = Color(0.5, 1.0, 1.0, 1.0); Color debug_navigation_geometry_face_color = Color(0.5, 1.0, 1.0, 0.4); Color debug_navigation_geometry_edge_disabled_color = Color(0.5, 0.5, 0.5, 1.0); 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); + bool debug_navigation_enable_edge_connections = true; bool debug_navigation_enable_edge_connections_xray = true; bool debug_navigation_enable_edge_lines = true; bool debug_navigation_enable_edge_lines_xray = true; bool debug_navigation_enable_geometry_face_random_color = true; + bool debug_navigation_enable_link_connections = true; + bool debug_navigation_enable_link_connections_xray = true; Ref<StandardMaterial3D> debug_navigation_geometry_edge_material; Ref<StandardMaterial3D> debug_navigation_geometry_face_material; Ref<StandardMaterial3D> debug_navigation_geometry_edge_disabled_material; Ref<StandardMaterial3D> debug_navigation_geometry_face_disabled_material; Ref<StandardMaterial3D> debug_navigation_edge_connections_material; + Ref<StandardMaterial3D> debug_navigation_link_connections_material; + Ref<StandardMaterial3D> debug_navigation_link_connections_disabled_material; + +public: + void set_debug_enabled(bool p_enabled); + bool get_debug_enabled() const; void set_debug_navigation_edge_connection_color(const Color &p_color); Color get_debug_navigation_edge_connection_color() const; @@ -248,6 +295,12 @@ public: void set_debug_navigation_geometry_face_disabled_color(const Color &p_color); Color get_debug_navigation_geometry_face_disabled_color() const; + void set_debug_navigation_link_connection_color(const Color &p_color); + Color get_debug_navigation_link_connection_color() const; + + 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_enable_edge_connections(const bool p_value); bool get_debug_navigation_enable_edge_connections() const; @@ -263,11 +316,19 @@ public: void set_debug_navigation_enable_geometry_face_random_color(const bool p_value); bool get_debug_navigation_enable_geometry_face_random_color() const; + void set_debug_navigation_enable_link_connections(const bool p_value); + bool get_debug_navigation_enable_link_connections() const; + + void set_debug_navigation_enable_link_connections_xray(const bool p_value); + bool get_debug_navigation_enable_link_connections_xray() 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(); Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_disabled_material(); 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(); #endif // DEBUG_ENABLED }; diff --git a/servers/physics_2d/godot_body_direct_state_2d.cpp b/servers/physics_2d/godot_body_direct_state_2d.cpp index cde6e8c991..d413e03be6 100644 --- a/servers/physics_2d/godot_body_direct_state_2d.cpp +++ b/servers/physics_2d/godot_body_direct_state_2d.cpp @@ -138,7 +138,7 @@ void GodotPhysicsDirectBodyState2D::add_constant_torque(real_t p_torque) { } void GodotPhysicsDirectBodyState2D::set_constant_force(const Vector2 &p_force) { - if (!p_force.is_equal_approx(Vector2())) { + if (!p_force.is_zero_approx()) { body->wakeup(); } body->set_constant_force(p_force); diff --git a/servers/physics_2d/godot_collision_solver_2d.cpp b/servers/physics_2d/godot_collision_solver_2d.cpp index 0d7b42b80d..761a1c33e2 100644 --- a/servers/physics_2d/godot_collision_solver_2d.cpp +++ b/servers/physics_2d/godot_collision_solver_2d.cpp @@ -34,7 +34,7 @@ #define collision_solver sat_2d_calculate_penetration //#define collision_solver gjk_epa_calculate_penetration -bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { +bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) { const GodotWorldBoundaryShape2D *world_boundary = static_cast<const GodotWorldBoundaryShape2D *>(p_shape_A); if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) { return false; @@ -52,7 +52,9 @@ bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_s bool found = false; for (int i = 0; i < support_count; i++) { + supports[i] += p_margin * supports[i].normalized(); supports[i] = p_transform_B.xform(supports[i]); + supports[i] += p_motion_B; real_t pd = n.dot(supports[i]); if (pd >= d) { continue; @@ -231,9 +233,9 @@ bool GodotCollisionSolver2D::solve(const GodotShape2D *p_shape_A, const Transfor } if (swap) { - return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); + return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_motion_A, p_result_callback, p_userdata, true, p_margin_A); } else { - return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); + return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, p_margin_B); } } else if (type_A == PhysicsServer2D::SHAPE_SEPARATION_RAY) { diff --git a/servers/physics_2d/godot_collision_solver_2d.h b/servers/physics_2d/godot_collision_solver_2d.h index bd90641f04..3aac2751e0 100644 --- a/servers/physics_2d/godot_collision_solver_2d.h +++ b/servers/physics_2d/godot_collision_solver_2d.h @@ -38,7 +38,7 @@ public: typedef void (*CallbackResult)(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata); private: - static bool solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0); static bool concave_callback(void *p_userdata, GodotShape2D *p_convex); static bool solve_concave(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); static bool solve_separation_ray(const GodotShape2D *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin = 0); diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp index c728dccd4f..cec31bdc31 100644 --- a/servers/physics_2d/godot_physics_server_2d.cpp +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -848,7 +848,7 @@ void GodotPhysicsServer2D::body_set_constant_force(RID p_body, const Vector2 &p_ ERR_FAIL_COND(!body); body->set_constant_force(p_force); - if (!p_force.is_equal_approx(Vector2())) { + if (!p_force.is_zero_approx()) { body->wakeup(); } } diff --git a/servers/physics_3d/godot_body_direct_state_3d.cpp b/servers/physics_3d/godot_body_direct_state_3d.cpp index a8c6086e1c..25088d33f3 100644 --- a/servers/physics_3d/godot_body_direct_state_3d.cpp +++ b/servers/physics_3d/godot_body_direct_state_3d.cpp @@ -145,7 +145,7 @@ void GodotPhysicsDirectBodyState3D::add_constant_torque(const Vector3 &p_torque) } void GodotPhysicsDirectBodyState3D::set_constant_force(const Vector3 &p_force) { - if (!p_force.is_equal_approx(Vector3())) { + if (!p_force.is_zero_approx()) { body->wakeup(); } body->set_constant_force(p_force); @@ -156,7 +156,7 @@ Vector3 GodotPhysicsDirectBodyState3D::get_constant_force() const { } void GodotPhysicsDirectBodyState3D::set_constant_torque(const Vector3 &p_torque) { - if (!p_torque.is_equal_approx(Vector3())) { + if (!p_torque.is_zero_approx()) { body->wakeup(); } body->set_constant_torque(p_torque); diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp index 20e9300778..56e644b57b 100644 --- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp +++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp @@ -629,7 +629,7 @@ public: _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) { Vector3 axis = p_axis; - if (axis.is_equal_approx(Vector3())) { + if (axis.is_zero_approx()) { // strange case, try an upwards separator axis = Vector3(0.0, 1.0, 0.0); } diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp index 9c1535f561..b028c00a31 100644 --- a/servers/physics_3d/godot_physics_server_3d.cpp +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -760,7 +760,7 @@ void GodotPhysicsServer3D::body_set_constant_force(RID p_body, const Vector3 &p_ ERR_FAIL_COND(!body); body->set_constant_force(p_force); - if (!p_force.is_equal_approx(Vector3())) { + if (!p_force.is_zero_approx()) { body->wakeup(); } } @@ -776,7 +776,7 @@ void GodotPhysicsServer3D::body_set_constant_torque(RID p_body, const Vector3 &p ERR_FAIL_COND(!body); body->set_constant_torque(p_torque); - if (!p_torque.is_equal_approx(Vector3())) { + if (!p_torque.is_zero_approx()) { body->wakeup(); } } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index ca9c9c8fc4..abaa473017 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -148,7 +148,7 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {} /////////////////////////////////////////////////////// -Ref<PhysicsRayQueryParameters2D> PhysicsRayQueryParameters2D::create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) { +Ref<PhysicsRayQueryParameters2D> PhysicsRayQueryParameters2D::create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const TypedArray<RID> &p_exclude) { Ref<PhysicsRayQueryParameters2D> params; params.instantiate(); params->set_from(p_from); @@ -158,25 +158,25 @@ Ref<PhysicsRayQueryParameters2D> PhysicsRayQueryParameters2D::create(Vector2 p_f return params; } -void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { +void PhysicsRayQueryParameters2D::set_exclude(const TypedArray<RID> &p_exclude) { parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { parameters.exclude.insert(p_exclude[i]); } } -Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const { - Vector<RID> ret; +TypedArray<RID> PhysicsRayQueryParameters2D::get_exclude() const { + TypedArray<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; for (const RID &E : parameters.exclude) { - ret.write[idx++] = E; + ret[idx++] = E; } return ret; } void PhysicsRayQueryParameters2D::_bind_methods() { - ClassDB::bind_static_method("PhysicsRayQueryParameters2D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters2D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>())); + ClassDB::bind_static_method("PhysicsRayQueryParameters2D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters2D::create, DEFVAL(UINT32_MAX), DEFVAL(TypedArray<RID>())); ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from); ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from); @@ -210,19 +210,19 @@ void PhysicsRayQueryParameters2D::_bind_methods() { /////////////////////////////////////////////////////// -void PhysicsPointQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { +void PhysicsPointQueryParameters2D::set_exclude(const TypedArray<RID> &p_exclude) { parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { parameters.exclude.insert(p_exclude[i]); } } -Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const { - Vector<RID> ret; +TypedArray<RID> PhysicsPointQueryParameters2D::get_exclude() const { + TypedArray<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; for (const RID &E : parameters.exclude) { - ret.write[idx++] = E; + ret[idx++] = E; } return ret; } @@ -269,19 +269,19 @@ void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { } } -void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) { +void PhysicsShapeQueryParameters2D::set_exclude(const TypedArray<RID> &p_exclude) { parameters.exclude.clear(); for (int i = 0; i < p_exclude.size(); i++) { parameters.exclude.insert(p_exclude[i]); } } -Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const { - Vector<RID> ret; +TypedArray<RID> PhysicsShapeQueryParameters2D::get_exclude() const { + TypedArray<RID> ret; ret.resize(parameters.exclude.size()); int idx = 0; for (const RID &E : parameters.exclude) { - ret.write[idx++] = E; + ret[idx++] = E; } return ret; } @@ -461,21 +461,21 @@ void PhysicsDirectSpaceState2D::_bind_methods() { /////////////////////////////// -Vector<RID> PhysicsTestMotionParameters2D::get_exclude_bodies() const { - Vector<RID> exclude; +TypedArray<RID> PhysicsTestMotionParameters2D::get_exclude_bodies() const { + TypedArray<RID> exclude; exclude.resize(parameters.exclude_bodies.size()); int body_index = 0; for (RID body : parameters.exclude_bodies) { - exclude.write[body_index++] = body; + exclude[body_index++] = body; } return exclude; } -void PhysicsTestMotionParameters2D::set_exclude_bodies(const Vector<RID> &p_exclude) { - for (RID body : p_exclude) { - parameters.exclude_bodies.insert(body); +void PhysicsTestMotionParameters2D::set_exclude_bodies(const TypedArray<RID> &p_exclude) { + for (int i = 0; i < p_exclude.size(); i++) { + parameters.exclude_bodies.insert(p_exclude[i]); } } @@ -850,6 +850,8 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_BIAS); BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_FORCE); + BIND_ENUM_CONSTANT(PIN_JOINT_SOFTNESS); + BIND_ENUM_CONSTANT(DAMPED_SPRING_REST_LENGTH); BIND_ENUM_CONSTANT(DAMPED_SPRING_STIFFNESS); BIND_ENUM_CONSTANT(DAMPED_SPRING_DAMPING); @@ -874,9 +876,7 @@ PhysicsServer2D::~PhysicsServer2D() { singleton = nullptr; } -Vector<PhysicsServer2DManager::ClassInfo> PhysicsServer2DManager::physics_2d_servers; -int PhysicsServer2DManager::default_server_id = -1; -int PhysicsServer2DManager::default_server_priority = -1; +PhysicsServer2DManager *PhysicsServer2DManager::singleton = nullptr; const String PhysicsServer2DManager::setting_property_name(PNAME("physics/2d/physics_engine")); void PhysicsServer2DManager::on_servers_changed() { @@ -887,10 +887,19 @@ void PhysicsServer2DManager::on_servers_changed() { ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers)); } -void PhysicsServer2DManager::register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback) { - ERR_FAIL_COND(!p_creat_callback); +void PhysicsServer2DManager::_bind_methods() { + ClassDB::bind_method(D_METHOD("register_server", "name", "create_callback"), &PhysicsServer2DManager::register_server); + ClassDB::bind_method(D_METHOD("set_default_server", "name", "priority"), &PhysicsServer2DManager::set_default_server); +} + +PhysicsServer2DManager *PhysicsServer2DManager::get_singleton() { + return singleton; +} + +void PhysicsServer2DManager::register_server(const String &p_name, const Callable &p_create_callback) { + //ERR_FAIL_COND(!p_create_callback.is_valid()); ERR_FAIL_COND(find_server_id(p_name) != -1); - physics_2d_servers.push_back(ClassInfo(p_name, p_creat_callback)); + physics_2d_servers.push_back(ClassInfo(p_name, p_create_callback)); on_servers_changed(); } @@ -923,7 +932,11 @@ String PhysicsServer2DManager::get_server_name(int p_id) { PhysicsServer2D *PhysicsServer2DManager::new_default_server() { ERR_FAIL_COND_V(default_server_id == -1, nullptr); - return physics_2d_servers[default_server_id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_2d_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer2D>(ret.get_validated_object()); } PhysicsServer2D *PhysicsServer2DManager::new_server(const String &p_name) { @@ -931,6 +944,18 @@ PhysicsServer2D *PhysicsServer2DManager::new_server(const String &p_name) { if (id == -1) { return nullptr; } else { - return physics_2d_servers[id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_2d_servers[id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer2D>(ret.get_validated_object()); } } + +PhysicsServer2DManager::PhysicsServer2DManager() { + singleton = this; +} + +PhysicsServer2DManager::~PhysicsServer2DManager() { + singleton = nullptr; +} diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 071ff5ffe9..d5b4dc05e6 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -610,7 +610,7 @@ protected: static void _bind_methods(); public: - static Ref<PhysicsRayQueryParameters2D> create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const Vector<RID> &p_exclude); + static Ref<PhysicsRayQueryParameters2D> create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const TypedArray<RID> &p_exclude); const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; } void set_from(const Vector2 &p_from) { parameters.from = p_from; } @@ -631,8 +631,8 @@ public: void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; } bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; } - void set_exclude(const Vector<RID> &p_exclude); - Vector<RID> get_exclude() const; + void set_exclude(const TypedArray<RID> &p_exclude); + TypedArray<RID> get_exclude() const; }; class PhysicsPointQueryParameters2D : public RefCounted { @@ -661,8 +661,8 @@ public: void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } - void set_exclude(const Vector<RID> &p_exclude); - Vector<RID> get_exclude() const; + void set_exclude(const TypedArray<RID> &p_exclude); + TypedArray<RID> get_exclude() const; }; class PhysicsShapeQueryParameters2D : public RefCounted { @@ -702,8 +702,8 @@ public: void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; } bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; } - void set_exclude(const Vector<RID> &p_exclude); - Vector<RID> get_exclude() const; + void set_exclude(const TypedArray<RID> &p_exclude); + TypedArray<RID> get_exclude() const; }; class PhysicsTestMotionParameters2D : public RefCounted { @@ -729,8 +729,8 @@ public: bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; } void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; } - Vector<RID> get_exclude_bodies() const; - void set_exclude_bodies(const Vector<RID> &p_exclude); + TypedArray<RID> get_exclude_bodies() const; + void set_exclude_bodies(const TypedArray<RID> &p_exclude); Array get_exclude_objects() const; void set_exclude_objects(const Array &p_exclude); @@ -766,16 +766,18 @@ public: real_t get_collision_unsafe_fraction() const; }; -typedef PhysicsServer2D *(*CreatePhysicsServer2DCallback)(); +class PhysicsServer2DManager : public Object { + GDCLASS(PhysicsServer2DManager, Object); + + static PhysicsServer2DManager *singleton; -class PhysicsServer2DManager { struct ClassInfo { String name; - CreatePhysicsServer2DCallback create_callback = nullptr; + Callable create_callback; ClassInfo() {} - ClassInfo(String p_name, CreatePhysicsServer2DCallback p_create_callback) : + ClassInfo(String p_name, Callable p_create_callback) : name(p_name), create_callback(p_create_callback) {} @@ -789,24 +791,30 @@ class PhysicsServer2DManager { } }; - static Vector<ClassInfo> physics_2d_servers; - static int default_server_id; - static int default_server_priority; + Vector<ClassInfo> physics_2d_servers; + int default_server_id = -1; + int default_server_priority = -1; + + void on_servers_changed(); + +protected: + static void _bind_methods(); public: static const String setting_property_name; -private: - static void on_servers_changed(); + static PhysicsServer2DManager *get_singleton(); -public: - static void register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback); - static void set_default_server(const String &p_name, int p_priority = 0); - static int find_server_id(const String &p_name); - static int get_servers_count(); - static String get_server_name(int p_id); - static PhysicsServer2D *new_default_server(); - static PhysicsServer2D *new_server(const String &p_name); + void register_server(const String &p_name, const Callable &p_create_callback); + void set_default_server(const String &p_name, int p_priority = 0); + int find_server_id(const String &p_name); + int get_servers_count(); + String get_server_name(int p_id); + PhysicsServer2D *new_default_server(); + PhysicsServer2D *new_server(const String &p_name); + + PhysicsServer2DManager(); + ~PhysicsServer2DManager(); }; VARIANT_ENUM_CAST(PhysicsServer2D::ShapeType); @@ -820,6 +828,7 @@ VARIANT_ENUM_CAST(PhysicsServer2D::BodyState); VARIANT_ENUM_CAST(PhysicsServer2D::CCDMode); VARIANT_ENUM_CAST(PhysicsServer2D::JointParam); VARIANT_ENUM_CAST(PhysicsServer2D::JointType); +VARIANT_ENUM_CAST(PhysicsServer2D::PinJointParam); VARIANT_ENUM_CAST(PhysicsServer2D::DampedSpringParam); VARIANT_ENUM_CAST(PhysicsServer2D::AreaBodyStatus); VARIANT_ENUM_CAST(PhysicsServer2D::ProcessInfo); diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index fc32e1f665..b4f30d7649 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -1046,9 +1046,7 @@ PhysicsServer3D::~PhysicsServer3D() { singleton = nullptr; } -Vector<PhysicsServer3DManager::ClassInfo> PhysicsServer3DManager::physics_servers; -int PhysicsServer3DManager::default_server_id = -1; -int PhysicsServer3DManager::default_server_priority = -1; +PhysicsServer3DManager *PhysicsServer3DManager::singleton = nullptr; const String PhysicsServer3DManager::setting_property_name(PNAME("physics/3d/physics_engine")); void PhysicsServer3DManager::on_servers_changed() { @@ -1059,10 +1057,19 @@ void PhysicsServer3DManager::on_servers_changed() { ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2)); } -void PhysicsServer3DManager::register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback) { - ERR_FAIL_COND(!p_creat_callback); +void PhysicsServer3DManager::_bind_methods() { + ClassDB::bind_method(D_METHOD("register_server", "name", "create_callback"), &PhysicsServer3DManager::register_server); + ClassDB::bind_method(D_METHOD("set_default_server", "name", "priority"), &PhysicsServer3DManager::set_default_server); +} + +PhysicsServer3DManager *PhysicsServer3DManager::get_singleton() { + return singleton; +} + +void PhysicsServer3DManager::register_server(const String &p_name, const Callable &p_create_callback) { + //ERR_FAIL_COND(!p_create_callback.is_valid()); ERR_FAIL_COND(find_server_id(p_name) != -1); - physics_servers.push_back(ClassInfo(p_name, p_creat_callback)); + physics_servers.push_back(ClassInfo(p_name, p_create_callback)); on_servers_changed(); } @@ -1095,7 +1102,11 @@ String PhysicsServer3DManager::get_server_name(int p_id) { PhysicsServer3D *PhysicsServer3DManager::new_default_server() { ERR_FAIL_COND_V(default_server_id == -1, nullptr); - return physics_servers[default_server_id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer3D>(ret.get_validated_object()); } PhysicsServer3D *PhysicsServer3DManager::new_server(const String &p_name) { @@ -1103,6 +1114,18 @@ PhysicsServer3D *PhysicsServer3DManager::new_server(const String &p_name) { if (id == -1) { return nullptr; } else { - return physics_servers[id].create_callback(); + Variant ret; + Callable::CallError ce; + physics_servers[id].create_callback.callp(nullptr, 0, ret, ce); + ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr); + return Object::cast_to<PhysicsServer3D>(ret.get_validated_object()); } } + +PhysicsServer3DManager::PhysicsServer3DManager() { + singleton = this; +} + +PhysicsServer3DManager::~PhysicsServer3DManager() { + singleton = nullptr; +} diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 6237ed67aa..1308e4cd36 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -983,16 +983,18 @@ public: real_t get_collision_depth(int p_collision_index = 0) const; }; -typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)(); +class PhysicsServer3DManager : public Object { + GDCLASS(PhysicsServer3DManager, Object); + + static PhysicsServer3DManager *singleton; -class PhysicsServer3DManager { struct ClassInfo { String name; - CreatePhysicsServer3DCallback create_callback = nullptr; + Callable create_callback; ClassInfo() {} - ClassInfo(String p_name, CreatePhysicsServer3DCallback p_create_callback) : + ClassInfo(String p_name, Callable p_create_callback) : name(p_name), create_callback(p_create_callback) {} @@ -1006,24 +1008,30 @@ class PhysicsServer3DManager { } }; - static Vector<ClassInfo> physics_servers; - static int default_server_id; - static int default_server_priority; + Vector<ClassInfo> physics_servers; + int default_server_id = -1; + int default_server_priority = -1; + + void on_servers_changed(); + +protected: + static void _bind_methods(); public: static const String setting_property_name; -private: - static void on_servers_changed(); + static PhysicsServer3DManager *get_singleton(); -public: - static void register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback); - static void set_default_server(const String &p_name, int p_priority = 0); - static int find_server_id(const String &p_name); - static int get_servers_count(); - static String get_server_name(int p_id); - static PhysicsServer3D *new_default_server(); - static PhysicsServer3D *new_server(const String &p_name); + void register_server(const String &p_name, const Callable &p_create_callback); + void set_default_server(const String &p_name, int p_priority = 0); + int find_server_id(const String &p_name); + int get_servers_count(); + String get_server_name(int p_id); + PhysicsServer3D *new_default_server(); + PhysicsServer3D *new_server(const String &p_name); + + PhysicsServer3DManager(); + ~PhysicsServer3DManager(); }; VARIANT_ENUM_CAST(PhysicsServer3D::ShapeType); diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index db473f6296..b9667f338c 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -72,6 +72,7 @@ #include "rendering/rendering_device.h" #include "rendering/rendering_device_binds.h" #include "rendering_server.h" +#include "servers/extensions/physics_server_2d_extension.h" #include "servers/extensions/physics_server_3d_extension.h" #include "servers/rendering/shader_types.h" #include "text/text_server_dummy.h" @@ -84,7 +85,7 @@ ShaderTypes *shader_types = nullptr; -PhysicsServer3D *_createGodotPhysics3DCallback() { +static PhysicsServer3D *_createGodotPhysics3DCallback() { bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread"); PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads)); @@ -92,7 +93,7 @@ PhysicsServer3D *_createGodotPhysics3DCallback() { return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads)); } -PhysicsServer2D *_createGodotPhysics2DCallback() { +static PhysicsServer2D *_createGodotPhysics2DCallback() { bool using_threads = GLOBAL_GET("physics/2d/run_on_separate_thread"); PhysicsServer2D *physics_server_2d = memnew(GodotPhysicsServer2D(using_threads)); @@ -132,7 +133,23 @@ void register_server_types() { GDREGISTER_ABSTRACT_CLASS(RenderingServer); GDREGISTER_CLASS(AudioServer); + GDREGISTER_CLASS(PhysicsServer2DManager); + Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2DManager", PhysicsServer2DManager::get_singleton(), "PhysicsServer2DManager")); + GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D); + GDREGISTER_VIRTUAL_CLASS(PhysicsServer2DExtension); + GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2DExtension); + GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2DExtension); + + GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionRayResult, "Vector2 position;Vector2 normal;RID rid;ObjectID collider_id;Object *collider;int shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeRestInfo, "Vector2 point;Vector2 normal;RID rid;ObjectID collider_id;int shape;Vector2 linear_velocity"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionMotionResult, "Vector2 travel;Vector2 remainder;Vector2 collision_point;Vector2 collision_normal;Vector2 collider_velocity;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;int collision_local_shape;ObjectID collider_id;RID collider;int collider_shape"); + GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState2D *p_state)"); + + GDREGISTER_CLASS(PhysicsServer3DManager); + Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3DManager", PhysicsServer3DManager::get_singleton(), "PhysicsServer3DManager")); + GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D); GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension); GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension); @@ -253,15 +270,15 @@ void register_server_types() { GLOBAL_DEF(PhysicsServer2DManager::setting_property_name, "DEFAULT"); ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer2DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer2DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); - PhysicsServer2DManager::register_server("GodotPhysics2D", &_createGodotPhysics2DCallback); - PhysicsServer2DManager::set_default_server("GodotPhysics2D"); + PhysicsServer2DManager::get_singleton()->register_server("GodotPhysics2D", callable_mp_static(_createGodotPhysics2DCallback)); + PhysicsServer2DManager::get_singleton()->set_default_server("GodotPhysics2D"); // Physics 3D GLOBAL_DEF(PhysicsServer3DManager::setting_property_name, "DEFAULT"); ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer3DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer3DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); - PhysicsServer3DManager::register_server("GodotPhysics3D", &_createGodotPhysics3DCallback); - PhysicsServer3DManager::set_default_server("GodotPhysics3D"); + PhysicsServer3DManager::get_singleton()->register_server("GodotPhysics3D", callable_mp_static(_createGodotPhysics3DCallback)); + PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D"); writer_mjpeg = memnew(MovieWriterMJPEG); MovieWriter::add_writer(writer_mjpeg); diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h index 0d368b765a..4a2a947b94 100644 --- a/servers/rendering/dummy/rasterizer_scene_dummy.h +++ b/servers/rendering/dummy/rasterizer_scene_dummy.h @@ -106,10 +106,10 @@ public: /* SDFGI UPDATE */ - void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} - int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } - AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } - uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } + void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} + int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; } + AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); } + uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; } /* SKY API */ @@ -180,7 +180,7 @@ public: void voxel_gi_set_quality(RS::VoxelGIQuality) override {} - void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} + void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {} void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {} void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {} @@ -188,8 +188,7 @@ public: void set_time(double p_time, double p_step) override {} void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {} - RID render_buffers_create() override { return RID(); } - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {} + Ref<RenderSceneBuffers> render_buffers_create() override { return Ref<RenderSceneBuffers>(); } void gi_set_use_half_resolution(bool p_enable) override {} void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {} @@ -198,7 +197,7 @@ public: void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {} void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {} - TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } + TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); } bool free(RID p_rid) override { if (is_environment(p_rid)) { diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h index e25a2ac3a9..ed8fefc558 100644 --- a/servers/rendering/dummy/storage/material_storage.h +++ b/servers/rendering/dummy/storage/material_storage.h @@ -40,21 +40,21 @@ class MaterialStorage : public RendererMaterialStorage { public: /* GLOBAL SHADER UNIFORM API */ - virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override {} - virtual void global_shader_uniform_remove(const StringName &p_name) override {} - virtual Vector<StringName> global_shader_uniform_get_list() const override { return Vector<StringName>(); } + virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) override {} + virtual void global_shader_parameter_remove(const StringName &p_name) override {} + virtual Vector<StringName> global_shader_parameter_get_list() const override { return Vector<StringName>(); } - virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override {} - virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override {} - virtual Variant global_shader_uniform_get(const StringName &p_name) const override { return Variant(); } - virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } + virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) override {} + virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) override {} + virtual Variant global_shader_parameter_get(const StringName &p_name) const override { return Variant(); } + virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; } - virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override {} - virtual void global_shader_uniforms_clear() override {} + virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override {} + virtual void global_shader_parameters_clear() override {} - virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override { return 0; } - virtual void global_shader_uniforms_instance_free(RID p_instance) override {} - virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} + virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override { return 0; } + virtual void global_shader_parameters_instance_free(RID p_instance) override {} + virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value) override {} /* SHADER API */ @@ -66,11 +66,11 @@ public: virtual void shader_set_path_hint(RID p_shader, const String &p_code) override {} virtual String shader_get_code(RID p_shader) const override { return ""; } - virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} + virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {} - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } - virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); } + virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {} + virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); } + virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const override { return Variant(); } virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); }; @@ -89,7 +89,7 @@ public: virtual bool material_is_animated(RID p_material) override { return false; } virtual bool material_casts_shadows(RID p_material) override { return false; } - virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override {} + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {} virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {} }; diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h index 1eb4fd854f..b0914e70e4 100644 --- a/servers/rendering/dummy/storage/mesh_storage.h +++ b/servers/rendering/dummy/storage/mesh_storage.h @@ -81,6 +81,7 @@ public: s->vertex_count = p_surface.vertex_count; s->index_data = p_surface.index_data; s->index_count = p_surface.index_count; + s->skin_data = p_surface.skin_data; } virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; } @@ -98,6 +99,7 @@ public: virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { DummyMesh *m = mesh_owner.get_or_null(p_mesh); ERR_FAIL_COND_V(!m, RS::SurfaceData()); + ERR_FAIL_INDEX_V(p_surface, m->surfaces.size(), RS::SurfaceData()); RS::SurfaceData s = m->surfaces[p_surface]; return s; } diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index 70f5fc4a6a..53237c1dfb 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -705,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con RD::get_singleton()->compute_list_end(); } -void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) { +void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) { ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer."); UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); @@ -713,6 +713,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc MaterialStorage *material_storage = MaterialStorage::get_singleton(); ERR_FAIL_NULL(material_storage); + RID half_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_half_texture); + RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture); + memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant)); BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; @@ -737,14 +740,14 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); - RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half })); + RD::Uniform u_half_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_half_texture })); RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode); ERR_FAIL_COND(shader.is_null()); //HORIZONTAL - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(half_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); if (p_auto_exposure.is_valid() && p_first_pass) { RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure })); @@ -764,9 +767,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc ERR_FAIL_COND(shader.is_null()); //VERTICAL - draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0); + draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); blur_raster.push_constant.flags = base_flags; @@ -810,9 +813,11 @@ void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const RD::get_singleton()->compute_list_end(); } -void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) { +void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) { ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer."); + RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture); + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -833,8 +838,8 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebu RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode); ERR_FAIL_COND(shader.is_null()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array()); RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant)); diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index f82726d654..0ddb60ebef 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -322,10 +322,10 @@ public: void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false); void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); - void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); + void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0); void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); - void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size); + void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); diff --git a/servers/rendering/renderer_rd/effects/fsr.cpp b/servers/rendering/renderer_rd/effects/fsr.cpp new file mode 100644 index 0000000000..5fde24a926 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/fsr.cpp @@ -0,0 +1,127 @@ +/*************************************************************************/ +/* fsr.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "fsr.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" + +using namespace RendererRD; + +FSR::FSR() { + Vector<String> FSR_upscale_modes; + +#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) + // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though. + FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); +#else + // Everyone else can use normal mode when available. + if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) { + FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n"); + } else { + FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); + } +#endif + + fsr_shader.initialize(FSR_upscale_modes); + + shader_version = fsr_shader.version_create(); + pipeline = RD::get_singleton()->compute_pipeline_create(fsr_shader.version_get_shader(shader_version, 0)); +} + +FSR::~FSR() { + fsr_shader.version_free(shader_version); +} + +void FSR::fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + Size2i internal_size = p_render_buffers->get_internal_size(); + Size2i target_size = p_render_buffers->get_target_size(); + float fsr_upscale_sharpness = p_render_buffers->get_fsr_sharpness(); + + if (!p_render_buffers->has_texture(SNAME("FSR"), SNAME("upscale_texture"))) { + RD::DataFormat format = p_render_buffers->get_base_data_format(); + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + uint32_t layers = 1; // we only need one layer, in multiview we're processing one layer at a time. + + p_render_buffers->create_texture(SNAME("FSR"), SNAME("upscale_texture"), format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size, layers); + } + + RID upscale_texture = p_render_buffers->get_texture(SNAME("FSR"), SNAME("upscale_texture")); + + FSRUpscalePushConstant push_constant; + memset(&push_constant, 0, sizeof(FSRUpscalePushConstant)); + + int dispatch_x = (target_size.x + 15) / 16; + int dispatch_y = (target_size.y + 15) / 16; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline); + + push_constant.resolution_width = internal_size.width; + push_constant.resolution_height = internal_size.height; + push_constant.upscaled_width = target_size.width; + push_constant.upscaled_height = target_size.height; + push_constant.sharpness = fsr_upscale_sharpness; + + RID shader = fsr_shader.version_get_shader(shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + //FSR Easc + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, p_source_rd_texture }); + RD::Uniform u_upscale_texture(RD::UNIFORM_TYPE_IMAGE, 0, { upscale_texture }); + + push_constant.pass = FSR_UPSCALE_PASS_EASU; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_upscale_texture), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //FSR Rcas + RD::Uniform u_upscale_texture_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, upscale_texture }); + RD::Uniform u_destination_texture(RD::UNIFORM_TYPE_IMAGE, 0, { p_destination_texture }); + + push_constant.pass = FSR_UPSCALE_PASS_RCAS; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_texture_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_destination_texture), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1); + + RD::get_singleton()->compute_list_end(compute_list); +} diff --git a/servers/rendering/renderer_rd/effects/fsr.h b/servers/rendering/renderer_rd/effects/fsr.h new file mode 100644 index 0000000000..1adfba527a --- /dev/null +++ b/servers/rendering/renderer_rd/effects/fsr.h @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* fsr.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef FSR_RD_H +#define FSR_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class FSR { +public: + FSR(); + ~FSR(); + + void fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture); + +private: + enum FSRUpscalePass { + FSR_UPSCALE_PASS_EASU = 0, + FSR_UPSCALE_PASS_RCAS = 1 + }; + + struct FSRUpscalePushConstant { + float resolution_width; + float resolution_height; + float upscaled_width; + float upscaled_height; + float sharpness; + int pass; + int _unused0, _unused1; + }; + + FsrUpscaleShaderRD fsr_shader; + RID shader_version; + RID pipeline; +}; + +} // namespace RendererRD + +#endif // FSR_RD_H diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 874409b885..582c5abbdd 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -32,6 +32,7 @@ #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" using namespace RendererRD; @@ -333,6 +334,22 @@ SSEffects::SSEffects() { } } } + + // Subsurface scattering + { + Vector<String> sss_modes; + sss_modes.push_back("\n#define USE_11_SAMPLES\n"); + sss_modes.push_back("\n#define USE_17_SAMPLES\n"); + sss_modes.push_back("\n#define USE_25_SAMPLES\n"); + + sss.shader.initialize(sss_modes); + + sss.shader_version = sss.shader.version_create(); + + for (int i = 0; i < sss_modes.size(); i++) { + sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i)); + } + } } SSEffects::~SSEffects() { @@ -376,6 +393,11 @@ SSEffects::~SSEffects() { RD::get_singleton()->free(ssao.importance_map_load_counter); } + { + // Cleanup Subsurface scattering + sss.shader.version_free(sss.shader_version); + } + singleton = nullptr; } @@ -421,6 +443,11 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ RD::get_singleton()->draw_command_begin_label("Downsample Depth"); if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) { + if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) { + RD::get_singleton()->free(ss_effects.downsample_uniform_set); + ss_effects.downsample_uniform_set = RID(); + } + Vector<RD::Uniform> uniforms; { RD::Uniform u; @@ -494,6 +521,7 @@ void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_ ss_effects.used_full_mips_last_frame = use_full_mips; ss_effects.used_half_size_last_frame = use_half_size; + ss_effects.used_mips_last_frame = use_mips; } /* SSIL */ @@ -1462,7 +1490,7 @@ void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const Rend } } -void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) { +void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) { UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -1557,10 +1585,6 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]); push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; push_constant.proj_info[3] = (1.0f + p_projections[v].matrix[1][2]) / p_projections[v].matrix[1][1]; - push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255); - push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255); - push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255); - push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255); ScreenSpaceReflectionMode mode = (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL; RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode); @@ -1713,3 +1737,73 @@ void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) { p_ssr_buffers.normal_scaled = RID(); } } + +/* Subsurface scattering */ + +void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + // Our intermediate buffer is only created if we haven't created it already. + RD::DataFormat format = p_render_buffers->get_base_data_format(); + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + uint32_t layers = 1; // We only need one layer, we're handling one view at a time + uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH); + RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps); + + Plane p = p_camera.xform4(Plane(1, 0, -1, 1)); + p.normal /= p.d; + float unit_size = p.normal.x; + + { //scale color and depth to half + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + sss.push_constant.camera_z_far = p_camera.get_z_far(); + sss.push_constant.camera_z_near = p_camera.get_z_near(); + sss.push_constant.orthogonal = p_camera.is_orthogonal(); + sss.push_constant.unit_size = unit_size; + sss.push_constant.screen_size[0] = p_screen_size.x; + sss.push_constant.screen_size[1] = p_screen_size.y; + sss.push_constant.vertical = false; + sss.push_constant.scale = p_scale; + sss.push_constant.depth_scale = p_depth_scale; + + RID shader = sss.shader.version_get_shader(sss.shader_version, p_quality - 1); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]); + + RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse })); + RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse })); + RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate })); + RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate })); + RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth })); + + // horizontal + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + // vertical + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2); + + sss.push_constant.vertical = true; + RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); + + RD::get_singleton()->compute_list_end(); + } +} diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h index c31271ffd2..d50319c46f 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.h +++ b/servers/rendering/renderer_rd/effects/ss_effects.h @@ -44,9 +44,12 @@ #include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" +class RenderSceneBuffersRD; + namespace RendererRD { class SSEffects { @@ -165,9 +168,12 @@ public: }; void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, const Size2i &p_screen_size, const uint32_t p_view_count); - void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets); + void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets); void ssr_free(SSRRenderBuffers &p_ssr_buffers); + /* subsurface scattering */ + void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); + private: /* SS Downsampler */ @@ -459,10 +465,7 @@ private: uint32_t orthogonal; // 4 - 52 float filter_mipmap_levels; // 4 - 56 uint32_t use_half_res; // 4 - 60 - uint8_t metallic_mask[4]; // 4 - 64 - - uint32_t view_index; // 4 - 68 - uint32_t pad[3]; // 12 - 80 + uint32_t view_index; // 4 - 64 // float projection[16]; // this is in our ScreenSpaceReflectionSceneData now }; @@ -501,6 +504,29 @@ private: RID shader_version; RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX]; } ssr_filter; + + /* Subsurface scattering */ + + struct SubSurfaceScatteringPushConstant { + int32_t screen_size[2]; + float camera_z_far; + float camera_z_near; + + uint32_t vertical; + uint32_t orthogonal; + float unit_size; + float scale; + + float depth_scale; + uint32_t pad[3]; + }; + + struct SubSurfaceScattering { + SubSurfaceScatteringPushConstant push_constant; + SubsurfaceScatteringShaderRD shader; + RID shader_version; + RID pipelines[3]; //3 quality levels + } sss; }; } // namespace RendererRD diff --git a/servers/rendering/renderer_rd/effects/taa.cpp b/servers/rendering/renderer_rd/effects/taa.cpp new file mode 100644 index 0000000000..657385a509 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/taa.cpp @@ -0,0 +1,138 @@ +/*************************************************************************/ +/* taa.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "taa.h" +#include "servers/rendering/renderer_rd/effects/copy_effects.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" + +using namespace RendererRD; + +TAA::TAA() { + Vector<String> taa_modes; + taa_modes.push_back("\n#define MODE_TAA_RESOLVE"); + taa_shader.initialize(taa_modes); + shader_version = taa_shader.version_create(); + pipeline = RD::get_singleton()->compute_pipeline_create(taa_shader.version_get_shader(shader_version, 0)); +} + +TAA::~TAA() { + taa_shader.version_free(shader_version); +} + +void TAA::msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers) { + if (!p_render_buffers->has_velocity_buffer(true)) { + // nothing to resolve + return; + } + + for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { + RID velocity_buffer_msaa = p_render_buffers->get_velocity_buffer(true, v); + RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v); + + RD::get_singleton()->texture_resolve_multisample(velocity_buffer_msaa, velocity_buffer); + } +} + +void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + RID shader = taa_shader.version_get_shader(shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + TAAResolvePushConstant push_constant; + memset(&push_constant, 0, sizeof(TAAResolvePushConstant)); + push_constant.resolution_width = p_resolution.width; + push_constant.resolution_height = p_resolution.height; + push_constant.disocclusion_threshold = 0.025f; + push_constant.disocclusion_scale = 10.0f; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline); + + RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame }); + RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth }); + RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity }); + RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity }); + RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history }); + RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp }); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(TAAResolvePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1); + RD::get_singleton()->compute_list_end(); +} + +void TAA::process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far) { + CopyEffects *copy_effects = CopyEffects::get_singleton(); + + uint32_t view_count = p_render_buffers->get_view_count(); + Size2i internal_size = p_render_buffers->get_internal_size(); + Size2i target_size = p_render_buffers->get_target_size(); + + bool just_allocated = false; + if (!p_render_buffers->has_texture(SNAME("taa"), SNAME("history"))) { + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + p_render_buffers->create_texture(SNAME("taa"), SNAME("history"), p_format, usage_bits); + p_render_buffers->create_texture(SNAME("taa"), SNAME("temp"), p_format, usage_bits); + + p_render_buffers->create_texture(SNAME("taa"), SNAME("prev_velocity"), RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits); + + just_allocated = true; + } + + RD::get_singleton()->draw_command_begin_label("TAA"); + + for (uint32_t v = 0; v < view_count; v++) { + // Get our (cached) slices + RID internal_texture = p_render_buffers->get_internal_texture(v); + RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v); + RID taa_history = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("history"), v, 0); + RID taa_prev_velocity = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("prev_velocity"), v, 0); + + if (!just_allocated) { + RID depth_texture = p_render_buffers->get_depth_texture(v); + RID taa_temp = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("temp"), v, 0); + resolve(internal_texture, taa_temp, depth_texture, velocity_buffer, taa_prev_velocity, taa_history, Size2(internal_size.x, internal_size.y), p_z_near, p_z_far); + copy_effects->copy_to_rect(taa_temp, internal_texture, Rect2(0, 0, internal_size.x, internal_size.y)); + } + + copy_effects->copy_to_rect(internal_texture, taa_history, Rect2(0, 0, internal_size.x, internal_size.y)); + copy_effects->copy_to_rect(velocity_buffer, taa_prev_velocity, Rect2(0, 0, target_size.x, target_size.y)); + } + + RD::get_singleton()->draw_command_end_label(); +} diff --git a/servers/rendering/renderer_rd/effects/taa.h b/servers/rendering/renderer_rd/effects/taa.h new file mode 100644 index 0000000000..ce4af18866 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/taa.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* taa.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef TAA_RD_H +#define TAA_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class TAA { +public: + TAA(); + ~TAA(); + + void msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers); + void process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far); + +private: + struct TAAResolvePushConstant { + float resolution_width; + float resolution_height; + float disocclusion_threshold; + float disocclusion_scale; + }; + + TaaResolveShaderRD taa_shader; + RID shader_version; + RID pipeline; + + void resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far); +}; + +} // namespace RendererRD + +#endif // TAA_RD_H diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp index 68cfd43d90..5ff00aa94c 100644 --- a/servers/rendering/renderer_rd/effects/vrs.cpp +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -91,47 +91,22 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi RD::get_singleton()->draw_list_end(); } -void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) { - // TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm - +Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const { // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size // of the VRS buffer to supply. Size2i texel_size = Size2i(16, 16); - RD::TextureFormat tf; - if (p_view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - } - tf.format = RD::DATA_FORMAT_R8_UINT; - tf.width = p_base_width / texel_size.x; - if (p_base_width % texel_size.x != 0) { - tf.width++; + int width = p_base_size.x / texel_size.x; + if (p_base_size.x % texel_size.x != 0) { + width++; } - tf.height = p_base_height / texel_size.y; - if (p_base_height % texel_size.y != 0) { - tf.height++; + int height = p_base_size.y / texel_size.y; + if (p_base_size.y % texel_size.y != 0) { + height++; } - tf.array_layers = p_view_count; // create a layer for every view - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - tf.samples = RD::TEXTURE_SAMPLES_1; - - p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - // by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control - Vector<RID> fb; - fb.push_back(p_vrs_texture); - - RD::FramebufferPass pass; - pass.color_attachments.push_back(0); - - Vector<RD::FramebufferPass> passes; - passes.push_back(pass); - - p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count); + return Size2i(width, height); } void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h index dd15df615e..7125c6455d 100644 --- a/servers/rendering/renderer_rd/effects/vrs.h +++ b/servers/rendering/renderer_rd/effects/vrs.h @@ -66,7 +66,7 @@ public: void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false); - void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb); + Size2i get_vrs_texture_size(const Size2i p_base_size) const; void update_vrs_texture(RID p_vrs_fb, RID p_render_target); }; diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index 8d59b24f3f..b03415f2e3 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -108,115 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m return uniform_set; } -void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) { - memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant)); - - int dispatch_x = (p_size.x + 15) / 16; - int dispatch_y = (p_size.y + 15) / 16; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline); - - FSR_upscale.push_constant.resolution_width = p_internal_size.width; - FSR_upscale.push_constant.resolution_height = p_internal_size.height; - FSR_upscale.push_constant.upscaled_width = p_size.width; - FSR_upscale.push_constant.upscaled_height = p_size.height; - FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness; - - //FSR Easc - FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU; - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - //FSR Rcas - FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS; - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1); - - RD::get_singleton()->compute_list_end(compute_list); -} - -void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) { - UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); - ERR_FAIL_NULL(uniform_set_cache); - - RID shader = TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0); - ERR_FAIL_COND(shader.is_null()); - - memset(&TAA_resolve.push_constant, 0, sizeof(TAAResolvePushConstant)); - TAA_resolve.push_constant.resolution_width = p_resolution.width; - TAA_resolve.push_constant.resolution_height = p_resolution.height; - TAA_resolve.push_constant.disocclusion_threshold = 0.025f; - TAA_resolve.push_constant.disocclusion_scale = 10.0f; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, TAA_resolve.pipeline); - - RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame }); - RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth }); - RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity }); - RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity }); - RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history }); - RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp }); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &TAA_resolve.push_constant, sizeof(TAAResolvePushConstant)); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1); - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) { - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - Plane p = p_camera.xform4(Plane(1, 0, -1, 1)); - p.normal /= p.d; - float unit_size = p.normal.x; - - { //scale color and depth to half - sss.push_constant.camera_z_far = p_camera.get_z_far(); - sss.push_constant.camera_z_near = p_camera.get_z_near(); - sss.push_constant.orthogonal = p_camera.is_orthogonal(); - sss.push_constant.unit_size = unit_size; - sss.push_constant.screen_size[0] = p_screen_size.x; - sss.push_constant.screen_size[1] = p_screen_size.y; - sss.push_constant.vertical = false; - sss.push_constant.scale = p_scale; - sss.push_constant.depth_scale = p_depth_scale; - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse2), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - - RD::get_singleton()->compute_list_add_barrier(compute_list); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse2), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2); - - sss.push_constant.vertical = true; - RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1); - - RD::get_singleton()->compute_list_end(); - } -} - void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer."); @@ -377,27 +268,6 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) { } EffectsRD::EffectsRD(bool p_prefer_raster_effects) { - { - Vector<String> FSR_upscale_modes; - -#if defined(MACOS_ENABLED) || defined(IOS_ENABLED) - // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though. - FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); -#else - // Everyone else can use normal mode when available. - if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) { - FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n"); - } else { - FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); - } -#endif - - FSR_upscale.shader.initialize(FSR_upscale_modes); - - FSR_upscale.shader_version = FSR_upscale.shader.version_create(); - FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0)); - } - prefer_raster_effects = p_prefer_raster_effects; if (prefer_raster_effects) { @@ -445,23 +315,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0)); } - if (!prefer_raster_effects) { - { - Vector<String> sss_modes; - sss_modes.push_back("\n#define USE_11_SAMPLES\n"); - sss_modes.push_back("\n#define USE_17_SAMPLES\n"); - sss_modes.push_back("\n#define USE_25_SAMPLES\n"); - - sss.shader.initialize(sss_modes); - - sss.shader_version = sss.shader.version_create(); - - for (int i = 0; i < sss_modes.size(); i++) { - sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i)); - } - } - } - { Vector<String> sort_modes; sort_modes.push_back("\n#define MODE_SORT_BLOCK\n"); @@ -477,14 +330,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } } - { - Vector<String> taa_modes; - taa_modes.push_back("\n#define MODE_TAA_RESOLVE"); - TAA_resolve.shader.initialize(taa_modes); - TAA_resolve.shader_version = TAA_resolve.shader.version_create(); - TAA_resolve.pipeline = RD::get_singleton()->compute_pipeline_create(TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0)); - } - RD::SamplerState sampler; sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; @@ -523,8 +368,6 @@ EffectsRD::~EffectsRD() { RD::get_singleton()->free(default_mipmap_sampler); RD::get_singleton()->free(index_buffer); //array gets freed as dependency - FSR_upscale.shader.version_free(FSR_upscale.shader_version); - TAA_resolve.shader.version_free(TAA_resolve.shader_version); if (prefer_raster_effects) { luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version); } else { @@ -532,7 +375,6 @@ EffectsRD::~EffectsRD() { } if (!prefer_raster_effects) { roughness_limiter.shader.version_free(roughness_limiter.shader_version); - sss.shader.version_free(sss.shader_version); } sort.shader.version_free(sort.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 94cd26fae9..b05af73cf3 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -33,13 +33,10 @@ #include "core/math/projection.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" -#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" @@ -48,42 +45,6 @@ class EffectsRD { private: bool prefer_raster_effects; - enum FSRUpscalePass { - FSR_UPSCALE_PASS_EASU = 0, - FSR_UPSCALE_PASS_RCAS = 1 - }; - - struct FSRUpscalePushConstant { - float resolution_width; - float resolution_height; - float upscaled_width; - float upscaled_height; - float sharpness; - int pass; - int _unused0, _unused1; - }; - - struct FSRUpscale { - FSRUpscalePushConstant push_constant; - FsrUpscaleShaderRD shader; - RID shader_version; - RID pipeline; - } FSR_upscale; - - struct TAAResolvePushConstant { - float resolution_width; - float resolution_height; - float disocclusion_threshold; - float disocclusion_scale; - }; - - struct TAAResolve { - TAAResolvePushConstant push_constant; - TaaResolveShaderRD shader; - RID shader_version; - RID pipeline; - } TAA_resolve; - enum LuminanceReduceMode { LUMINANCE_REDUCE_READ, LUMINANCE_REDUCE, @@ -143,27 +104,6 @@ private: } roughness_limiter; - struct SubSurfaceScatteringPushConstant { - int32_t screen_size[2]; - float camera_z_far; - float camera_z_near; - - uint32_t vertical; - uint32_t orthogonal; - float unit_size; - float scale; - - float depth_scale; - uint32_t pad[3]; - }; - - struct SubSurfaceScattering { - SubSurfaceScatteringPushConstant push_constant; - SubsurfaceScatteringShaderRD shader; - RID shader_version; - RID pipelines[3]; //3 quality levels - } sss; - enum SortMode { SORT_MODE_BLOCK, SORT_MODE_STEP, @@ -230,16 +170,11 @@ private: public: bool get_prefer_raster_effects(); - void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness); - void taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far); - void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); - void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); - void sort_buffer(RID p_uniform_set, int p_size); EffectsRD(bool p_prefer_raster_effects); diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 257b67cf04..a41552cd5c 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -361,7 +361,7 @@ void Fog::FogShaderData::set_code(const String &p_code) { valid = true; } -void Fog::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void Fog::FogShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -430,7 +430,7 @@ void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::I } } -bool Fog::FogShaderData::is_param_texture(const StringName &p_param) const { +bool Fog::FogShaderData::is_parameter_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -473,7 +473,7 @@ Fog::FogShaderData::~FogShaderData() { //////////////////////////////////////////////////////////////////////////////// // Volumetric Fog -Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) { +void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) { width = fog_size.x; height = fog_size.y; depth = fog_size.z; @@ -591,6 +591,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RENDER_TIMESTAMP("> Volumetric Fog"); RD::get_singleton()->draw_command_begin_label("Volumetric Fog"); + Ref<VolumetricFog> fog = p_settings.vfog; + if (p_fog_volumes.size() > 0) { RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes"); @@ -623,9 +625,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P params.z_far = z_far; params.time = p_settings.time; - params.fog_volume_size[0] = p_settings.vfog->width; - params.fog_volume_size[1] = p_settings.vfog->height; - params.fog_volume_size[2] = p_settings.vfog->depth; + params.fog_volume_size[0] = fog->width; + params.fog_volume_size[1] = fog->height; + params.fog_volume_size[2] = fog->depth; params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env); params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; @@ -638,7 +640,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); - if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) { + if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) { Vector<RD::Uniform> uniforms; { @@ -649,7 +651,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 1; - u.append_id(p_settings.vfog->emissive_map); + u.append_id(fog->emissive_map); uniforms.push_back(u); } @@ -669,7 +671,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 3; - u.append_id(p_settings.vfog->density_map); + u.append_id(fog->density_map); uniforms.push_back(u); } @@ -681,11 +683,11 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 4; - u.append_id(p_settings.vfog->light_map); + u.append_id(fog->light_map); uniforms.push_back(u); } - p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); } RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -731,7 +733,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { // Local fog volume. Vector3i points[8]; - Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth); float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); @@ -742,7 +744,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform); - min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1); + min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1); max = Vector3i(1, 1, 1); for (int j = 0; j < 8; j++) { @@ -753,9 +755,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P kernel_size = max - min; } else { // Volume type global runs on all cells - extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + extents = Vector3(fog->width, fog->height, fog->depth); min = Vector3i(0, 0, 0); - kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth)); + kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth)); } if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) { @@ -777,7 +779,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant)); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE); if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set. @@ -795,7 +797,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_end(); } - if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) { + if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) { //re create uniform set if needed Vector<RD::Uniform> uniforms; Vector<RD::Uniform> copy_uniforms; @@ -875,7 +877,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 8; - u.append_id(p_settings.vfog->light_density_map); + u.append_id(fog->light_density_map); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -884,7 +886,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(p_settings.vfog->fog_map); + u.append_id(fog->fog_map); uniforms.push_back(u); } @@ -892,7 +894,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(p_settings.vfog->prev_light_density_map); + u.append_id(fog->prev_light_density_map); copy_uniforms.push_back(u); } @@ -909,7 +911,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 11; - u.append_id(p_settings.voxel_gl_buffer); + u.append_id(p_settings.voxel_gi_buffer); uniforms.push_back(u); copy_uniforms.push_back(u); } @@ -944,7 +946,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 15; - u.append_id(p_settings.vfog->prev_light_density_map); + u.append_id(fog->prev_light_density_map); uniforms.push_back(u); } { @@ -955,7 +957,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 16; - u.append_id(p_settings.vfog->density_map); + u.append_id(fog->density_map); uniforms.push_back(u); } { @@ -966,7 +968,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 17; - u.append_id(p_settings.vfog->light_map); + u.append_id(fog->light_map); uniforms.push_back(u); } @@ -978,7 +980,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P u.uniform_type = RD::UNIFORM_TYPE_IMAGE; #endif u.binding = 18; - u.append_id(p_settings.vfog->emissive_map); + u.append_id(fog->emissive_map); uniforms.push_back(u); } @@ -992,9 +994,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P uniforms.push_back(u); } - p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); + fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); - p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); RID aux7 = uniforms.write[7].get_id(0); RID aux8 = uniforms.write[8].get_id(0); @@ -1002,17 +1004,17 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P uniforms.write[7].set_id(0, aux8); uniforms.write[8].set_id(0, aux7); - p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); uniforms.remove_at(8); uniforms.write[7].set_id(0, aux7); - p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); + fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); } - bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi != nullptr); + bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi.is_valid()); if (using_sdfgi) { - if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) { + if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) { Vector<RD::Uniform> uniforms; { @@ -1039,12 +1041,12 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P uniforms.push_back(u); } - p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); + fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1); } } - p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); - p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); + fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env); + fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env); VolumetricFogShader::ParamsUBO params; @@ -1079,9 +1081,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P params.ambient_color[2] = ambient_color.b; params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env); - params.fog_volume_size[0] = p_settings.vfog->width; - params.fog_volume_size[1] = p_settings.vfog->height; - params.fog_volume_size[2] = p_settings.vfog->depth; + params.fog_volume_size[0] = fog->width; + params.fog_volume_size[1] = fog->height; + params.fog_volume_size[2] = fog->depth; params.directional_light_count = p_directional_light_count; @@ -1149,19 +1151,19 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0); if (using_sdfgi) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1); } - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_add_barrier(compute_list); // Copy fog to history buffer if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) { RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_add_barrier(compute_list); } RD::get_singleton()->draw_command_end_label(); @@ -1172,8 +1174,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RENDER_TIMESTAMP("Filter Fog"); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_end(); //need restart for buffer update @@ -1183,8 +1185,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set2, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth); RD::get_singleton()->compute_list_add_barrier(compute_list); RD::get_singleton()->draw_command_end_label(); @@ -1194,8 +1196,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P RD::get_singleton()->draw_command_begin_label("Integrate Fog"); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0); - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1); RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER); diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h index 171f9f3b88..9ecd5699dc 100644 --- a/servers/rendering/renderer_rd/environment/fog.h +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -38,8 +38,11 @@ #include "servers/rendering/renderer_rd/environment/gi.h" #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h" #include "servers/rendering/storage/utilities.h" +#define RB_SCOPE_FOG SNAME("Fog") + namespace RendererRD { class Fog : public RendererFog { @@ -199,10 +202,10 @@ private: virtual void set_path_hint(const String &p_hint); virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; virtual Variant get_default_parameter(const StringName &p_parameter) const; @@ -261,7 +264,10 @@ public: void fog_instance_free(RID p_rid); /* Volumetric FOG */ - struct VolumetricFog { + class VolumetricFog : public RenderBufferCustomDataRD { + GDCLASS(VolumetricFog, RenderBufferCustomDataRD) + + public: enum { MAX_TEMPORAL_FRAMES = 16 }; @@ -290,7 +296,10 @@ public: int last_shadow_filter = -1; - VolumetricFog(const Vector3i &fog_size, RID p_sky_shader); + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; + virtual void free_data() override{}; + + void init(const Vector3i &fog_size, RID p_sky_shader); ~VolumetricFog(); }; @@ -304,7 +313,7 @@ public: uint32_t max_cluster_elements; bool volumetric_fog_filter_active; RID shadow_sampler; - RID voxel_gl_buffer; + RID voxel_gi_buffer; RID shadow_atlas_depth; RID omni_light_buffer; RID spot_light_buffer; @@ -312,11 +321,11 @@ public: RID directional_light_buffer; // Objects related to our render buffer - VolumetricFog *vfog; + Ref<VolumetricFog> vfog; ClusterBuilderRD *cluster_builder; GI *gi; - GI::SDFGI *sdfgi; - GI::RenderBuffersGI *rbgi; + Ref<GI::SDFGI> sdfgi; + Ref<GI::RenderBuffersGI> rbgi; RID env; SkyRD *sky; }; diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index bc4f8d5855..ced0f6380f 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -34,6 +34,7 @@ #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" @@ -384,6 +385,13 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) { return voxel_gi->sdf_texture; } +Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, nullptr); + + return &voxel_gi->dependency; +} + //////////////////////////////////////////////////////////////////////////////// // SDFGI @@ -1121,7 +1129,11 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env); } -void GI::SDFGI::erase() { +void GI::SDFGI::free_data() { + // we don't free things here, we handle SDFGI differently at the moment destructing the object when it needs to change. +} + +GI::SDFGI::~SDFGI() { for (uint32_t i = 0; i < cascades.size(); i++) { const SDFGI::Cascade &c = cascades[i]; RD::get_singleton()->free(c.light_data); @@ -1982,10 +1994,9 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r } } -void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) { +void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) { //print_line("rendering region " + itos(p_region)); - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... + ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but... AABB bounds; Vector3i from; Vector3i size; @@ -2342,9 +2353,8 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr } } -void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) { - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... +void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) { + ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but... RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights"); @@ -3572,25 +3582,27 @@ void GI::free() { } } -GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { - SDFGI *sdfgi = memnew(SDFGI); +Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { + Ref<SDFGI> sdfgi; + sdfgi.instantiate(); sdfgi->create(p_env, p_world_position, p_requested_history_size, this); return sdfgi; } -void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { +void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { + ERR_FAIL_COND(p_render_buffers.is_null()); + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_NULL(texture_storage); r_voxel_gi_instances_used = 0; - // feels a little dirty to use our container this way but.... - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(rb == nullptr); - - RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers); + Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); + ERR_FAIL_COND(rbgi.is_null()); + RID voxel_gi_buffer = rbgi->get_voxel_gi_buffer(); VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES]; bool voxel_gi_instances_changed = false; @@ -3601,7 +3613,7 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { RID texture; if (i < (int)p_voxel_gi_instances.size()) { - VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]); + VoxelGIInstance *gipi = voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]); if (gipi) { texture = gipi->texture; @@ -3653,28 +3665,30 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } - if (texture != rb->rbgi.voxel_gi_textures[i]) { + if (texture != rbgi->voxel_gi_textures[i]) { voxel_gi_instances_changed = true; - rb->rbgi.voxel_gi_textures[i] = texture; + rbgi->voxel_gi_textures[i] = texture; } } if (voxel_gi_instances_changed) { for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - if (RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { - RD::get_singleton()->free(rb->rbgi.uniform_set[v]); + if (RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) { + RD::get_singleton()->free(rbgi->uniform_set[v]); } - rb->rbgi.uniform_set[v] = RID(); + rbgi->uniform_set[v] = RID(); } - if (rb->volumetric_fog) { - if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { - RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set); - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set); - RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2); + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); + + if (RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) { + RD::get_singleton()->free(fog->fog_uniform_set); + RD::get_singleton()->free(fog->process_uniform_set); + RD::get_singleton()->free(fog->process_uniform_set2); } - rb->volumetric_fog->fog_uniform_set = RID(); - rb->volumetric_fog->process_uniform_set = RID(); - rb->volumetric_fog->process_uniform_set2 = RID(); + fog->fog_uniform_set = RID(); + fog->process_uniform_set = RID(); + fog->process_uniform_set2 = RID(); } } @@ -3687,7 +3701,14 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff } } -void GI::RenderBuffersGI::free() { +RID GI::RenderBuffersGI::get_voxel_gi_buffer() { + if (voxel_gi_buffer.is_null()) { + voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::VoxelGIData) * GI::MAX_VOXEL_GI_INSTANCES); + } + return voxel_gi_buffer; +} + +void GI::RenderBuffersGI::free_data() { for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) { RD::get_singleton()->free(uniform_set[v]); @@ -3700,28 +3721,13 @@ void GI::RenderBuffersGI::free() { scene_data_ubo = RID(); } - if (ambient_buffer.is_valid()) { - RD::get_singleton()->free(ambient_buffer); - RD::get_singleton()->free(reflection_buffer); - ambient_buffer = RID(); - reflection_buffer = RID(); - - // these are automatically freed when we free the textures, so just reset.. - for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - ambient_slice[v] = RID(); - reflection_slice[v] = RID(); - } - - view_count = 0; - } - if (voxel_gi_buffer.is_valid()) { RD::get_singleton()->free(voxel_gi_buffer); voxel_gi_buffer = RID(); } } -void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { +void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3729,65 +3735,38 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::get_singleton()->draw_command_begin_label("GI Render"); - RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(rb == nullptr); + ERR_FAIL_COND(p_render_buffers.is_null()); - if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) { - // Free our old buffer if applicable - if (rb->rbgi.ambient_buffer.is_valid()) { - RD::get_singleton()->free(rb->rbgi.ambient_buffer); - RD::get_singleton()->free(rb->rbgi.reflection_buffer); + Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); + ERR_FAIL_COND(rbgi.is_null()); - for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - rb->rbgi.ambient_slice[v] = RID(); - rb->rbgi.reflection_slice[v] = RID(); - } - } + Size2i internal_size = p_render_buffers->get_internal_size(); + + if (rbgi->using_half_size_gi != half_resolution) { + p_render_buffers->clear_context(RB_SCOPE_GI); + } - // Remember the view count we're using - rb->rbgi.view_count = p_view_count; + if (!p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) { + Size2i size = internal_size; + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - // Create textures for our ambient and reflection data - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->internal_width; - tf.height = rb->internal_height; if (half_resolution) { - tf.width >>= 1; - tf.height >>= 1; - } - if (p_view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.array_layers = p_view_count; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - } - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer"); - rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer"); - rb->rbgi.using_half_size_gi = half_resolution; - - if (p_view_count == 1) { - // Just copy, we don't need to create slices - rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer; - rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer; - } else { - for (uint32_t v = 0; v < p_view_count; v++) { - rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); - rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); - } + size.x >>= 1; + size.y >>= 1; } + + p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_AMBIENT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size); + p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_REFLECTION, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size); + + rbgi->using_half_size_gi = half_resolution; } // Setup our scene data { SceneData scene_data; - if (rb->rbgi.scene_data_ubo.is_null()) { - rb->rbgi.scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData)); + if (rbgi->scene_data_ubo.is_null()) { + rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData)); } for (uint32_t v = 0; v < p_view_count; v++) { @@ -3801,10 +3780,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, // Note that we will be ignoring the origin of this transform. RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform); - scene_data.screen_size[0] = rb->internal_width; - scene_data.screen_size[1] = rb->internal_height; + scene_data.screen_size[0] = internal_size.x; + scene_data.screen_size[1] = internal_size.y; - RD::get_singleton()->buffer_update(rb->rbgi.scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); + RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); } // Now compute the contents of our buffers. @@ -3826,22 +3805,28 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, push_constant.z_far = p_projections[0].get_z_far(); // these are only used if we have 1 view, else we use the projections in our scene data - push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]); - push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]); + push_constant.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].matrix[1][1]); push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0]; push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1]; - bool use_sdfgi = rb->sdfgi != nullptr; + bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI); bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; + Ref<SDFGI> sdfgi; + if (use_sdfgi) { + sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); + } + uint32_t pipeline_specialization = 0; - if (rb->rbgi.using_half_size_gi) { + if (rbgi->using_half_size_gi) { pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES; } if (p_view_count > 1) { pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX; } - if (p_vrs_slices[0].is_valid()) { + bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE); + if (has_vrs_texture) { pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS; } @@ -3851,15 +3836,15 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, push_constant.view_index = v; // setup our uniform set - if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { + if (rbgi->uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) { Vector<RD::Uniform> uniforms; { RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].sdf_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].sdf_tex); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } @@ -3871,8 +3856,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].light_tex); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } @@ -3884,8 +3869,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].light_aniso_0_tex); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } @@ -3897,8 +3882,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); + if (use_sdfgi && j < sdfgi->cascades.size()) { + u.append_id(sdfgi->cascades[j].light_aniso_1_tex); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } @@ -3909,8 +3894,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 5; - if (rb->sdfgi) { - u.append_id(rb->sdfgi->occlusion_texture); + if (use_sdfgi) { + u.append_id(sdfgi->occlusion_texture); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); } @@ -3935,7 +3920,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 9; - u.append_id(rb->rbgi.ambient_slice[v]); + u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0)); uniforms.push_back(u); } @@ -3943,7 +3928,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 10; - u.append_id(rb->rbgi.reflection_slice[v]); + u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0)); uniforms.push_back(u); } @@ -3951,8 +3936,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 11; - if (rb->sdfgi) { - u.append_id(rb->sdfgi->lightprobe_texture); + if (use_sdfgi) { + u.append_id(sdfgi->lightprobe_texture); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); } @@ -3962,7 +3947,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; - u.append_id(rb->views[v].view_depth); + u.append_id(p_render_buffers->get_depth_texture(v)); uniforms.push_back(u); } { @@ -3991,7 +3976,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 16; - u.append_id(rb->rbgi.voxel_gi_buffer); + u.append_id(rbgi->get_voxel_gi_buffer()); uniforms.push_back(u); } { @@ -3999,7 +3984,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 17; for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { - u.append_id(rb->rbgi.voxel_gi_textures[i]); + u.append_id(rbgi->voxel_gi_textures[i]); } uniforms.push_back(u); } @@ -4007,29 +3992,29 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; u.binding = 18; - u.append_id(rb->rbgi.scene_data_ubo); + u.append_id(rbgi->scene_data_ubo); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; u.binding = 19; - RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS); + RID buffer = has_vrs_texture ? p_render_buffers->get_texture_slice(RB_SCOPE_VRS, RB_TEXTURE, v, 0) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS); u.append_id(buffer); uniforms.push_back(u); } - rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); + rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); } RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); - if (rb->rbgi.using_half_size_gi) { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1); + if (rbgi->using_half_size_gi) { + RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x >> 1, internal_size.y >> 1, 1); } else { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x, internal_size.y, 1); } } @@ -4053,21 +4038,21 @@ void GI::voxel_gi_instance_free(RID p_rid) { } void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND(!voxel_gi); voxel_gi->transform = p_xform; } bool GI::voxel_gi_needs_update(RID p_probe) const { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND_V(!voxel_gi, false); return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe); } void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND(!voxel_gi); voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); diff --git a/servers/rendering/renderer_rd/environment/gi.h b/servers/rendering/renderer_rd/environment/gi.h index 9ef1914333..e567c67a3b 100644 --- a/servers/rendering/renderer_rd/environment/gi.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -44,10 +44,17 @@ #include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/storage/utilities.h" +#define RB_SCOPE_GI SNAME("rbgi") +#define RB_SCOPE_SDFGI SNAME("sdfgi") + +#define RB_TEX_AMBIENT SNAME("ambient") +#define RB_TEX_REFLECTION SNAME("reflection") + // Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound struct RenderDataRD; class RendererSceneRenderRD; @@ -89,6 +96,60 @@ public: Dependency dependency; }; + /* VOXEL_GI INSTANCE */ + + //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. + + struct VoxelGIInstance { + // access to our containers + GI *gi = nullptr; + + RID probe; + RID texture; + RID write_buffer; + + struct Mipmap { + RID texture; + RID uniform_set; + RID second_bounce_uniform_set; + RID write_uniform_set; + uint32_t level; + uint32_t cell_offset; + uint32_t cell_count; + }; + Vector<Mipmap> mipmaps; + + struct DynamicMap { + RID texture; //color normally, or emission on first pass + RID fb_depth; //actual depth buffer for the first pass, float depth for later passes + RID depth; //actual depth buffer for the first pass, float depth for later passes + RID normal; //normal buffer for the first pass + RID albedo; //emission buffer for the first pass + RID orm; //orm buffer for the first pass + RID fb; //used for rendering, only valid on first map + RID uniform_set; + uint32_t size; + int mipmap; // mipmap to write to, -1 if no mipmap assigned + }; + + Vector<DynamicMap> dynamic_maps; + + int slot = -1; + uint32_t last_probe_version = 0; + uint32_t last_probe_data_version = 0; + + //uint64_t last_pass = 0; + uint32_t render_index = 0; + + bool has_dynamic_object_data = false; + + Transform3D transform; + + void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); + void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + void free_resources(); + }; + private: static GI *singleton; @@ -98,6 +159,8 @@ private: /* VOXEL_GI INSTANCE */ + mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; + struct VoxelGILight { uint32_t type; float energy; @@ -370,9 +433,40 @@ private: public: static GI *get_singleton() { return singleton; } + /* GI */ + + enum { + MAX_VOXEL_GI_INSTANCES = 8 + }; + + // Struct for use in render buffer + class RenderBuffersGI : public RenderBufferCustomDataRD { + GDCLASS(RenderBuffersGI, RenderBufferCustomDataRD) + + private: + RID voxel_gi_buffer; + + public: + RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; + + RID full_buffer; + RID full_dispatch; + RID full_mask; + + /* GI buffers */ + bool using_half_size_gi = false; + + RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; + RID scene_data_ubo; + + RID get_voxel_gi_buffer(); + + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; + virtual void free_data() override; + }; + /* VOXEL GI API */ - VoxelGI *get_voxel_gi(RID p_rid) { return voxel_gi_owner.get_or_null(p_rid); }; bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }; virtual RID voxel_gi_allocate() override; @@ -422,72 +516,23 @@ public: RID voxel_gi_get_sdf_texture(RID p_voxel_gi); - /* VOXEL_GI INSTANCE */ - - //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. - - struct VoxelGIInstance { - // access to our containers - GI *gi = nullptr; - - RID probe; - RID texture; - RID write_buffer; - - struct Mipmap { - RID texture; - RID uniform_set; - RID second_bounce_uniform_set; - RID write_uniform_set; - uint32_t level; - uint32_t cell_offset; - uint32_t cell_count; - }; - Vector<Mipmap> mipmaps; + Dependency *voxel_gi_get_dependency(RID p_voxel_gi) const; - struct DynamicMap { - RID texture; //color normally, or emission on first pass - RID fb_depth; //actual depth buffer for the first pass, float depth for later passes - RID depth; //actual depth buffer for the first pass, float depth for later passes - RID normal; //normal buffer for the first pass - RID albedo; //emission buffer for the first pass - RID orm; //orm buffer for the first pass - RID fb; //used for rendering, only valid on first map - RID uniform_set; - uint32_t size; - int mipmap; // mipmap to write to, -1 if no mipmap assigned - }; - - Vector<DynamicMap> dynamic_maps; - - int slot = -1; - uint32_t last_probe_version = 0; - uint32_t last_probe_data_version = 0; - - //uint64_t last_pass = 0; - uint32_t render_index = 0; - - bool has_dynamic_object_data = false; - - Transform3D transform; - - void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render); - void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); - void free_resources(); - }; - - mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner; - - _FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const { - return voxel_gi_instance_owner.get_or_null(p_probe); - }; + /* VOXEL_GI INSTANCE */ _FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) { - VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); ERR_FAIL_COND_V(!voxel_gi, RID()); return voxel_gi->texture; }; + _FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) { + VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe); + ERR_FAIL_NULL(voxel_gi); + + voxel_gi->render_index = p_index; + }; + bool voxel_gi_instance_owns(RID p_rid) const { return voxel_gi_instance_owner.owns(p_rid); } @@ -498,7 +543,10 @@ public: /* SDFGI */ - struct SDFGI { + class SDFGI : public RenderBufferCustomDataRD { + GDCLASS(SDFGI, RenderBufferCustomDataRD) + + public: enum { MAX_CASCADES = 8, CASCADE_SIZE = 128, @@ -624,8 +672,11 @@ public: int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically RID integrate_sky_uniform_set; + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{}; + virtual void free_data() override; + ~SDFGI(); + void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi); - void erase(); void update(RID p_env, const Vector3 &p_world_position); void update_light(); void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky); @@ -637,8 +688,8 @@ public: void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render); - void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization); - void render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render); + void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization); + void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render); }; RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16; @@ -655,34 +706,6 @@ public: int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; } - /* GI */ - enum { - MAX_VOXEL_GI_INSTANCES = 8 - }; - - // Struct for use in render buffer - struct RenderBuffersGI { - RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; - RID voxel_gi_buffer; - - RID full_buffer; - RID full_dispatch; - RID full_mask; - - /* GI buffers */ - RID ambient_buffer; - RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS]; - RID reflection_buffer; - RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS]; - bool using_half_size_gi = false; - uint32_t view_count = 1; - - RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; - RID scene_data_ubo; - - void free(); - }; - struct SDFGIData { float grid_size[3]; uint32_t max_cascades; @@ -787,10 +810,10 @@ public: void init(RendererRD::SkyRD *p_sky); void free(); - SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); + Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); - void setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); - void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); + void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); + void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances); RID voxel_gi_instance_create(RID p_base); void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index d1d18cdd83..307af99e91 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -35,6 +35,7 @@ #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" #include "servers/rendering/rendering_server_globals.h" @@ -151,7 +152,7 @@ void SkyRD::SkyShaderData::set_code(const String &p_code) { valid = true; } -void SkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void SkyRD::SkyShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -219,7 +220,7 @@ void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage: } } -bool SkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const { +bool SkyRD::SkyShaderData::is_parameter_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } @@ -906,6 +907,7 @@ void SkyRD::init() { actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n"; actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n"; actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; + actions.render_mode_defines["use_debanding"] = "#define USE_DEBANDING\n"; actions.sampler_array_name = "material_samplers"; actions.base_texture_binding_index = 1; @@ -1109,7 +1111,7 @@ SkyRD::~SkyRD() { RD::get_singleton()->free(index_buffer); //array gets freed as dependency } -void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { +void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); ERR_FAIL_COND(p_env.is_null()); @@ -1259,6 +1261,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh light_data_dirty = true; for (uint32_t i = sky_scene_state.ubo.directional_light_count; i < sky_scene_state.max_directional_lights; i++) { sky_scene_state.directional_lights[i].enabled = false; + sky_scene_state.last_frame_directional_lights[i].enabled = false; } } @@ -1294,24 +1297,25 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh //setup fog variables sky_scene_state.ubo.volumetric_fog_enabled = false; if (p_render_buffers.is_valid()) { - if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) { + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); sky_scene_state.ubo.volumetric_fog_enabled = true; - float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers); + float fog_end = fog->length; if (fog_end > 0.0) { sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end; } else { sky_scene_state.ubo.volumetric_fog_inv_length = 1.0; } - float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup + float fog_detail_spread = fog->spread; //reverse lookup if (fog_detail_spread > 0.0) { sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread; } else { sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0; } - sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers); + sky_scene_state.fog_uniform_set = fog->sky_uniform_set; } } @@ -1326,6 +1330,9 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env); + sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_env); + sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_env); + RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo); } diff --git a/servers/rendering/renderer_rd/environment/sky.h b/servers/rendering/renderer_rd/environment/sky.h index bac8f44ef7..45c4f9bda7 100644 --- a/servers/rendering/renderer_rd/environment/sky.h +++ b/servers/rendering/renderer_rd/environment/sky.h @@ -42,6 +42,7 @@ // Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound class RendererSceneRenderRD; +class RenderSceneBuffersRD; namespace RendererRD { @@ -129,10 +130,10 @@ private: virtual void set_code(const String &p_Code); virtual void set_path_hint(const String &p_hint); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; virtual Variant get_default_parameter(const StringName &p_parameter) const; @@ -147,20 +148,23 @@ private: public: struct SkySceneState { struct UBO { - uint32_t volumetric_fog_enabled; - float volumetric_fog_inv_length; - float volumetric_fog_detail_spread; - - float fog_aerial_perspective; - - float fog_light_color[3]; - float fog_sun_scatter; - - uint32_t fog_enabled; - float fog_density; - - float z_far; - uint32_t directional_light_count; + uint32_t volumetric_fog_enabled; // 4 - 4 + float volumetric_fog_inv_length; // 4 - 8 + float volumetric_fog_detail_spread; // 4 - 12 + float volumetric_fog_sky_affect; // 4 - 16 + + uint32_t fog_enabled; // 4 - 20 + float fog_sky_affect; // 4 - 24 + float fog_density; // 4 - 28 + float fog_sun_scatter; // 4 - 32 + + float fog_light_color[3]; // 12 - 44 + float fog_aerial_perspective; // 4 - 48 + + float z_far; // 4 - 52 + uint32_t directional_light_count; // 4 - 56 + uint32_t pad1; // 4 - 60 + uint32_t pad2; // 4 - 64 }; UBO ubo; @@ -296,7 +300,7 @@ public: void set_texture_format(RD::DataFormat p_texture_format); ~SkyRD(); - void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); + void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render); void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); 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 8421598275..935ea07f6b 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -30,6 +30,7 @@ #include "render_forward_clustered.h" #include "core/config/project_settings.h" +#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/light_storage.h" #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" @@ -41,286 +42,93 @@ using namespace RendererSceneRenderImplementation; -RenderForwardClustered::RenderBufferDataForwardClustered::~RenderBufferDataForwardClustered() { - clear(); -} - void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() { - if (!specular.is_valid()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - if (view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.array_layers = view_count; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - } - tf.width = width; - tf.height = height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - if (msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - } else { - tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - } + ERR_FAIL_NULL(render_buffers); - specular = RD::get_singleton()->texture_create(tf, RD::TextureView()); - if (view_count == 1) { - specular_views[0] = specular; + if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR)) { + RD::DataFormat format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; } else { - for (uint32_t v = 0; v < view_count; v++) { - specular_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular, v, 0); - } + usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } - if (msaa == RS::VIEWPORT_MSAA_DISABLED) { - { - Vector<RID> fb; - fb.push_back(specular); - - specular_only_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, view_count); - } - - } else { - tf.samples = texture_samples; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - if (view_count == 1) { - specular_msaa_views[0] = specular_msaa; - } else { - for (uint32_t v = 0; v < view_count; v++) { - specular_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), specular_msaa, v, 0); - } - } + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR, format, usage_bits); - { - Vector<RID> fb; - fb.push_back(specular_msaa); - - specular_only_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, view_count); - } + if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, format, usage_bits, texture_samples); } } } -void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_velocity() { - if (!velocity_buffer.is_valid()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16_SFLOAT; - tf.width = width; - tf.height = height; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; +void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_normal_roughness_texture() { + ERR_FAIL_NULL(render_buffers); - if (msaa != RS::VIEWPORT_MSAA_DISABLED) { - RD::TextureFormat tf_aa = tf; - tf_aa.samples = texture_samples; - tf_aa.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - velocity_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView()); + if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS)) { + RD::DataFormat format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - } - - velocity_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } -} - -void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() { - if (!voxelgi_buffer.is_valid()) { - RD::TextureFormat tf; - if (view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.array_layers = view_count; + if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - } - tf.format = RD::DATA_FORMAT_R8G8_UINT; - tf.width = width; - tf.height = height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; - - if (msaa != RS::VIEWPORT_MSAA_DISABLED) { - RD::TextureFormat tf_aa = tf; - tf_aa.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tf_aa.samples = texture_samples; - voxelgi_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView()); - - if (view_count == 1) { - voxelgi_msaa_views[0] = voxelgi_buffer_msaa; - } else { - for (uint32_t v = 0; v < view_count; v++) { - voxelgi_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), voxelgi_buffer_msaa, v, 0); - } - } - } else { - tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } - tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; - - voxelgi_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, format, usage_bits); - if (view_count == 1) { - voxelgi_views[0] = voxelgi_buffer; - } else { - for (uint32_t v = 0; v < view_count; v++) { - voxelgi_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), voxelgi_buffer, v, 0); - } + if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, format, usage_bits, texture_samples); } - - Vector<RID> fb; - if (msaa != RS::VIEWPORT_MSAA_DISABLED) { - fb.push_back(depth_msaa); - fb.push_back(normal_roughness_buffer_msaa); - fb.push_back(voxelgi_buffer_msaa); - } else { - fb.push_back(depth); - fb.push_back(normal_roughness_buffer); - fb.push_back(voxelgi_buffer); - } - - depth_normal_roughness_voxelgi_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, view_count); } } -void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { - // note, slices are freed automatically when the parent texture is freed so we just clear them. - for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { - color_views[v] = RID(); - depth_views[v] = RID(); - specular_views[v] = RID(); - specular_msaa_views[v] = RID(); - color_msaa_views[v] = RID(); - depth_msaa_views[v] = RID(); - normal_roughness_views[v] = RID(); - normal_roughness_msaa_views[v] = RID(); - voxelgi_views[v] = RID(); - voxelgi_msaa_views[v] = RID(); - vrs_views[v] = RID(); - } - - if (voxelgi_buffer != RID()) { - RD::get_singleton()->free(voxelgi_buffer); - voxelgi_buffer = RID(); +void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() { + ERR_FAIL_NULL(render_buffers); - if (voxelgi_buffer_msaa.is_valid()) { - RD::get_singleton()->free(voxelgi_buffer_msaa); - voxelgi_buffer_msaa = RID(); + if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI)) { + RD::DataFormat format = RD::DATA_FORMAT_R8G8_UINT; + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + if (render_buffers->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED) { + usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } - depth_normal_roughness_voxelgi_fb = RID(); - } - - if (color_msaa.is_valid()) { - RD::get_singleton()->free(color_msaa); - color_msaa = RID(); - } - - if (depth_msaa.is_valid()) { - RD::get_singleton()->free(depth_msaa); - depth_msaa = RID(); - } + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, format, usage_bits); - if (specular.is_valid()) { - if (specular_msaa.is_valid()) { - RD::get_singleton()->free(specular_msaa); - specular_msaa = RID(); + if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, format, usage_bits, texture_samples); } - RD::get_singleton()->free(specular); - specular = RID(); } +} - color = RID(); - color_only_fb = RID(); - depth = RID(); - depth_fb = RID(); - - color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations - - if (normal_roughness_buffer.is_valid()) { - RD::get_singleton()->free(normal_roughness_buffer); - normal_roughness_buffer = RID(); - - if (normal_roughness_buffer_msaa.is_valid()) { - RD::get_singleton()->free(normal_roughness_buffer_msaa); - normal_roughness_buffer_msaa = RID(); - } - - depth_normal_roughness_fb = RID(); +void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() { + // JIC, should already have been cleared + if (render_buffers) { + render_buffers->clear_context(RB_SCOPE_FORWARD_CLUSTERED); } if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) { RD::get_singleton()->free(render_sdfgi_uniform_set); } - - if (velocity_buffer != RID()) { - RD::get_singleton()->free(velocity_buffer); - velocity_buffer = RID(); - } - - if (velocity_buffer_msaa != RID()) { - RD::get_singleton()->free(velocity_buffer_msaa); - velocity_buffer_msaa = RID(); - } } -void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { - clear(); - - msaa = p_msaa; - use_taa = p_use_taa; - vrs = p_vrs_texture; - - width = p_width; - height = p_height; - view_count = p_view_count; - - color = p_color_buffer; - depth = p_depth_buffer; - - if (vrs.is_valid()) { - if (view_count == 1) { - // just reuse - vrs_views[0] = vrs; - } else { - // create slices - for (uint32_t v = 0; v < view_count; v++) { - vrs_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), vrs, v, 0); - } - } +void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RenderSceneBuffersRD *p_render_buffers) { + if (render_buffers) { + // JIC + free_data(); } - if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) { - { - Vector<RID> fb; - fb.push_back(p_color_buffer); - fb.push_back(depth); - if (vrs.is_valid()) { - fb.push_back(vrs); - } + render_buffers = p_render_buffers; + ERR_FAIL_NULL(render_buffers); - color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); - } - { - Vector<RID> fb; - fb.push_back(depth); + RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d(); - depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); - } - } else { - RD::TextureFormat tf; - if (view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - } - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = p_width; - tf.height = p_height; - tf.array_layers = view_count; // create a layer for every view - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) { + RD::DataFormat format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { RD::TEXTURE_SAMPLES_1, @@ -329,148 +137,112 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c RD::TEXTURE_SAMPLES_8, }; - texture_samples = ts[p_msaa]; - tf.samples = texture_samples; + texture_samples = ts[msaa_3d]; - color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + p_render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples); - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + p_render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples); + } +} - if (view_count == 1) { - // just reuse - color_views[0] = color; - depth_views[0] = depth; - color_msaa_views[0] = color_msaa; - depth_msaa_views[0] = depth_msaa; - } else { - // create slices - for (uint32_t v = 0; v < view_count; v++) { - color_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), color, v, 0); - depth_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), depth, v, 0); - color_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), color_msaa, v, 0); - depth_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), depth_msaa, v, 0); - } - } +RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_only_fb() { + ERR_FAIL_NULL_V(render_buffers, RID()); - { - Vector<RID> fb; - fb.push_back(color_msaa); - fb.push_back(depth_msaa); - if (vrs.is_valid()) { - fb.push_back(vrs); - } + bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED; - color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); - } - { - Vector<RID> fb; - fb.push_back(depth_msaa); + RID color = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA) : render_buffers->get_internal_texture(); + RID depth = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA) : render_buffers->get_depth_texture(); - depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); - } + if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) { + RID vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE); + + return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), color, depth, vrs_texture); + } else { + return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), color, depth); } } RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) { - if (color_framebuffers.has(p_color_pass_flags)) { - return color_framebuffers[p_color_pass_flags]; - } + ERR_FAIL_NULL_V(render_buffers, RID()); + bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED; - bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED; - - Vector<RID> fb; - fb.push_back(use_msaa ? color_msaa : color); + int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? render_buffers->get_view_count() : 1; + RID color = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA) : render_buffers->get_internal_texture(); + RID specular; if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) { ensure_specular(); - fb.push_back(use_msaa ? specular_msaa : specular); - } else { - fb.push_back(RID()); + specular = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_SPECULAR_MSAA : RB_TEX_SPECULAR); } + RID velocity_buffer; if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) { - ensure_velocity(); - fb.push_back(use_msaa ? velocity_buffer_msaa : velocity_buffer); - } else { - fb.push_back(RID()); + render_buffers->ensure_velocity(); + velocity_buffer = render_buffers->get_velocity_buffer(use_msaa); } - fb.push_back(use_msaa ? depth_msaa : depth); + RID depth = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA) : render_buffers->get_depth_texture(); - if (vrs.is_valid()) { - fb.push_back(vrs); - } + if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) { + RID vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE); - int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1; - RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count); - color_framebuffers[p_color_pass_flags] = framebuffer; - return framebuffer; + return FramebufferCacheRD::get_singleton()->get_cache_multiview(v_count, color, specular, velocity_buffer, depth, vrs_texture); + } else { + return FramebufferCacheRD::get_singleton()->get_cache_multiview(v_count, color, specular, velocity_buffer, depth); + } } -void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) { - ERR_FAIL_COND_MSG(rb->view_count > 2, "Only support up to two views for roughness texture"); +RID RenderForwardClustered::RenderBufferDataForwardClustered::get_depth_fb(DepthFrameBufferType p_type) { + ERR_FAIL_NULL_V(render_buffers, RID()); + bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED; - if (rb->normal_roughness_buffer.is_valid()) { - return; - } + RID depth = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA) : render_buffers->get_depth_texture(); - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tf.width = rb->width; - tf.height = rb->height; - if (rb->view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.array_layers = rb->view_count; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - } - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + switch (p_type) { + case DEPTH_FB: { + return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth); + } break; + case DEPTH_FB_ROUGHNESS: { + ensure_normal_roughness_texture(); - if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - } else { - tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - } + RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_ROUGHNESS_MSAA : RB_TEX_ROUGHNESS); - rb->normal_roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth, normal_roughness_buffer); + } break; + case DEPTH_FB_ROUGHNESS_VOXELGI: { + ensure_normal_roughness_texture(); + ensure_voxelgi(); - if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) { - Vector<RID> fb; - fb.push_back(rb->depth); - fb.push_back(rb->normal_roughness_buffer); - rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count); - } else { - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - tf.samples = rb->texture_samples; - rb->normal_roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_ROUGHNESS_MSAA : RB_TEX_ROUGHNESS); + RID voxelgi_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_VOXEL_GI_MSAA : RB_TEX_VOXEL_GI); - Vector<RID> fb; - fb.push_back(rb->depth_msaa); - fb.push_back(rb->normal_roughness_buffer_msaa); - rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count); + return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth, normal_roughness_buffer, voxelgi_buffer); + } break; + default: { + ERR_FAIL_V(RID()); + } break; } +} - if (rb->view_count == 1) { - rb->normal_roughness_views[0] = rb->normal_roughness_buffer; - if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - rb->normal_roughness_msaa_views[0] = rb->normal_roughness_buffer_msaa; - } - } else { - for (uint32_t v = 0; v < rb->view_count; v++) { - rb->normal_roughness_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->normal_roughness_buffer, v, 0); - if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - rb->normal_roughness_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->normal_roughness_buffer_msaa, v, 0); - } - } - } +RID RenderForwardClustered::RenderBufferDataForwardClustered::get_specular_only_fb() { + bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED; + + RID specular = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_SPECULAR_MSAA : RB_TEX_SPECULAR); + + return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), specular); } -RendererSceneRenderRD::RenderBufferData *RenderForwardClustered::_create_render_buffer_data() { - return memnew(RenderBufferDataForwardClustered); +void RenderForwardClustered::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) { + Ref<RenderBufferDataForwardClustered> data; + data.instantiate(); + p_render_buffers->set_custom_data(RB_SCOPE_FORWARD_CLUSTERED, data); + + Ref<RendererRD::GI::RenderBuffersGI> rbgi; + rbgi.instantiate(); + p_render_buffers->set_custom_data(RB_SCOPE_GI, rbgi); } bool RenderForwardClustered::free(RID p_rid) { @@ -705,6 +477,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p prev_material_uniform_set = material_uniform_set; } + if (surf->owner->base_flags & INSTANCE_DATA_FLAG_MULTIMESH) { + mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset); + } + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SceneState::PushConstant)); uint32_t instance_count = surf->owner->instance_count > 1 ? surf->owner->instance_count : element_info.repeat; @@ -801,46 +577,22 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p } void RenderForwardClustered::_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) { - //Projection projection = p_render_data->cam_projection; - //projection.flip_y(); // Vulkan and modern APIs use Y-Down - Projection correction; - correction.set_depth_correction(p_flip_y); - correction.add_jitter_offset(p_render_data->taa_jitter); - Projection projection = correction * p_render_data->cam_projection; + 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() ? reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); - //store camera into ubo - RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); - RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); - RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); - - for (uint32_t v = 0; v < p_render_data->view_count; v++) { - projection = correction * p_render_data->view_projection[v]; - RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); - RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); - - scene_state.ubo.eye_offset[v][0] = p_render_data->view_eye_offset[v].x; - scene_state.ubo.eye_offset[v][1] = p_render_data->view_eye_offset[v].y; - scene_state.ubo.eye_offset[v][2] = p_render_data->view_eye_offset[v].z; - scene_state.ubo.eye_offset[v][3] = 0.0; + // May do this earlier in RenderSceneRenderRD::render_scene + if (p_index >= (int)scene_state.uniform_buffers.size()) { + uint32_t from = scene_state.uniform_buffers.size(); + scene_state.uniform_buffers.resize(p_index + 1); + for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) { + scene_state.uniform_buffers[i] = p_render_data->scene_data->create_uniform_buffer(); + } } - scene_state.ubo.taa_jitter[0] = p_render_data->taa_jitter.x; - scene_state.ubo.taa_jitter[1] = p_render_data->taa_jitter.y; - - scene_state.ubo.z_far = p_render_data->z_far; - scene_state.ubo.z_near = p_render_data->z_near; - - scene_state.ubo.pancake_shadows = p_pancake_shadows; + p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers); - RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); - RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); - RendererRD::MaterialStorage::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); - RendererRD::MaterialStorage::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); - - Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size); - scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x; - scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y; + // now do implementation UBO scene_state.ubo.cluster_shift = get_shift_from_power_of_2(p_render_data->cluster_size); scene_state.ubo.max_cluster_element_count_div_32 = p_render_data->cluster_max_elements / 32; @@ -851,39 +603,26 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.cluster_width = cluster_screen_width; } - if (p_render_data->shadow_atlas.is_valid()) { - Vector2 sas = shadow_atlas_get_size(p_render_data->shadow_atlas); - scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x; - scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y; - } - { - Vector2 dss = directional_shadow_get_size(); - scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x; - scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y; - } - //time global variables - scene_state.ubo.time = time; - scene_state.ubo.gi_upscale_for_msaa = false; scene_state.ubo.volumetric_fog_enabled = false; - scene_state.ubo.fog_enabled = false; - if (p_render_data->render_buffers.is_valid()) { - RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); - if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { + if (rd.is_valid()) { + if (rd->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { scene_state.ubo.gi_upscale_for_msaa = true; } - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { + if (rd->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = rd->get_custom_data(RB_SCOPE_FOG); + scene_state.ubo.volumetric_fog_enabled = true; - float fog_end = render_buffers_get_volumetric_fog_end(p_render_data->render_buffers); + float fog_end = fog->length; if (fog_end > 0.0) { scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end; } else { scene_state.ubo.volumetric_fog_inv_length = 1.0; } - float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_data->render_buffers); //reverse lookup + float fog_detail_spread = fog->spread; //reverse lookup if (fog_detail_spread > 0.0) { scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread; } else { @@ -893,59 +632,8 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat } if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { - scene_state.ubo.use_ambient_light = true; - scene_state.ubo.ambient_light_color_energy[0] = 1; - scene_state.ubo.ambient_light_color_energy[1] = 1; - scene_state.ubo.ambient_light_color_energy[2] = 1; - scene_state.ubo.ambient_light_color_energy[3] = 1.0; - scene_state.ubo.use_ambient_cubemap = false; - scene_state.ubo.use_reflection_cubemap = false; scene_state.ubo.ss_effects_flags = 0; - } else if (is_environment(p_render_data->environment)) { - RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment); - RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment); - - float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment); - - scene_state.ubo.ambient_light_color_energy[3] = bg_energy_multiplier; - - scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment); - - //ambient - if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { - Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); - color = color.srgb_to_linear(); - - scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier; - scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier; - scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier; - scene_state.ubo.use_ambient_light = true; - scene_state.ubo.use_ambient_cubemap = false; - } else { - float energy = environment_get_ambient_light_energy(p_render_data->environment); - Color color = environment_get_ambient_light(p_render_data->environment); - color = color.srgb_to_linear(); - scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; - scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; - scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; - - Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); - sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; - RendererRD::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); - - scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; - scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; - } - - //specular - RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_render_data->environment); - if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) { - scene_state.ubo.use_reflection_cubemap = true; - } else { - scene_state.ubo.use_reflection_cubemap = false; - } - 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; @@ -954,98 +642,19 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat ss_flags |= environment_get_ssil_enabled(p_render_data->environment) ? 2 : 0; } scene_state.ubo.ss_effects_flags = ss_flags; - - scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment); - scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); - scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); - scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); - scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); - - Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear(); - float fog_energy = environment_get_fog_light_energy(p_render_data->environment); - - scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; - scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; - scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; - - scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment); - } else { - if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { - scene_state.ubo.use_ambient_light = false; - } else { - scene_state.ubo.use_ambient_light = true; - Color clear_color = p_default_bg_color; - clear_color = clear_color.srgb_to_linear(); - scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; - scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; - scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; - scene_state.ubo.ambient_light_color_energy[3] = 1.0; - } - - scene_state.ubo.use_ambient_cubemap = false; - scene_state.ubo.use_reflection_cubemap = false; scene_state.ubo.ss_effects_flags = 0; } - if (p_render_data->camera_attributes.is_valid()) { - scene_state.ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); - scene_state.ubo.IBL_exposure_normalization = 1.0; - if (is_environment(p_render_data->environment)) { - RID sky_rid = environment_get_sky(p_render_data->environment); - if (sky_rid.is_valid()) { - float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes) * environment_get_bg_intensity(p_render_data->environment) / _render_buffers_get_luminance_multiplier(); - scene_state.ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, sky.sky_get_baked_exposure(sky_rid)); - } - } - } else if (scene_state.ubo.emissive_exposure_normalization > 0.0) { - // This branch is triggered when using render_material(). - // Emissive is set outside the function, so don't set it. - // IBL isn't used don't set it. - } else { - scene_state.ubo.emissive_exposure_normalization = 1.0; - scene_state.ubo.IBL_exposure_normalization = 1.0; - } - - scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active(); - scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount(); - scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit(); - - if (p_render_data->render_buffers.is_valid()) { - RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); - if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { - memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO)); - - Projection prev_correction; - prev_correction.set_depth_correction(true); - prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter); - Projection prev_projection = prev_correction * p_render_data->prev_cam_projection; - - //store camera into ubo - RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix); - RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix); - RendererRD::MaterialStorage::store_transform(p_render_data->prev_cam_transform, scene_state.prev_ubo.inv_view_matrix); - RendererRD::MaterialStorage::store_transform(p_render_data->prev_cam_transform.affine_inverse(), scene_state.prev_ubo.view_matrix); - - for (uint32_t v = 0; v < p_render_data->view_count; v++) { - prev_projection = prev_correction * p_render_data->view_projection[v]; - RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix_view[v]); - RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix_view[v]); - } - scene_state.prev_ubo.taa_jitter[0] = p_render_data->prev_taa_jitter.x; - scene_state.prev_ubo.taa_jitter[1] = p_render_data->prev_taa_jitter.y; - scene_state.prev_ubo.time -= time_step; + if (p_index >= (int)scene_state.implementation_uniform_buffers.size()) { + uint32_t from = scene_state.implementation_uniform_buffers.size(); + scene_state.implementation_uniform_buffers.resize(p_index + 1); + for (uint32_t i = from; i < scene_state.implementation_uniform_buffers.size(); i++) { + scene_state.implementation_uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); } } - if (p_index >= (int)scene_state.uniform_buffers.size()) { - uint32_t from = scene_state.uniform_buffers.size(); - scene_state.uniform_buffers.resize(p_index + 1); - for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) { - scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO) * 2); - } - } - RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO) * 2, &scene_state.ubo_data, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.implementation_uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER); } void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) { @@ -1150,7 +759,7 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 }; return (p_indices - subtractor[p_primitive]) / divisor[p_primitive]; } -void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) { +void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, uint32_t p_color_pass_flags = 0, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); if (p_render_list == RENDER_LIST_OPAQUE) { @@ -1161,9 +770,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } uint32_t lightmap_captures_used = 0; - Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin); - near_plane.d += p_render_data->cam_projection.get_z_near(); - float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near(); + Plane near_plane = Plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); + near_plane.d += p_render_data->scene_data->cam_projection.get_z_near(); + float z_max = p_render_data->scene_data->cam_projection.get_z_far() - p_render_data->scene_data->cam_projection.get_z_near(); RenderList *rl = &render_list[p_render_list]; _update_dirty_geometry_instances(); @@ -1194,7 +803,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con float fade_alpha = 1.0; if (inst->fade_near || inst->fade_far) { - float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin); + float fade_dist = inst->transform.origin.distance_to(p_render_data->scene_data->cam_transform.origin); // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player. if (inst->fade_far && fade_dist > inst->fade_far_begin) { fade_alpha = Math::smoothstep(0.0f, 1.0f, 1.0f - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin)); @@ -1289,13 +898,13 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con // LOD - if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { //lod - Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal); - Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal); + Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->scene_data->lod_camera_plane.normal); + Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->scene_data->lod_camera_plane.normal); - float distance_min = p_render_data->lod_camera_plane.distance_to(lod_support_min); - float distance_max = p_render_data->lod_camera_plane.distance_to(lod_support_max); + float distance_min = p_render_data->scene_data->lod_camera_plane.distance_to(lod_support_min); + float distance_max = p_render_data->scene_data->lod_camera_plane.distance_to(lod_support_max); float distance = 0.0; @@ -1308,12 +917,12 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con distance = -distance_max; } - if (p_render_data->cam_orthogonal) { + if (p_render_data->scene_data->cam_orthogonal) { distance = 1.0; } uint32_t indices; - surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); + surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque @@ -1375,6 +984,12 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con scene_state.used_depth_texture = true; } + if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS && flags & INSTANCE_DATA_FLAG_MULTIMESH) { + if (RendererRD::MeshStorage::get_singleton()->_multimesh_enable_motion_vectors(inst->data->base)) { + inst->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(inst->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET); + } + } + } else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) { if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) { rl->add_element(surf); @@ -1433,9 +1048,11 @@ void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data, } void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { - RenderBufferDataForwardClustered *render_buffer = nullptr; - if (p_render_data->render_buffers.is_valid()) { - render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); + Ref<RenderSceneBuffersRD> rb; + Ref<RenderBufferDataForwardClustered> rb_data; + if (p_render_data && p_render_data->render_buffers.is_valid()) { + rb = p_render_data->render_buffers; + rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); } static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 }; @@ -1444,9 +1061,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Setup 3D Scene"); - //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size; - scene_state.ubo.directional_light_count = 0; - scene_state.ubo.opaque_prepass_threshold = 0.99f; + // 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()) { + p_render_data->scene_data->calculate_motion_vectors = true; + } else { + p_render_data->scene_data->calculate_motion_vectors = false; + } + + //p_render_data->scene_data->subsurface_scatter_width = subsurface_scatter_size; + p_render_data->scene_data->directional_light_count = 0; + p_render_data->scene_data->opaque_prepass_threshold = 0.99f; Size2i screen_size; RID color_framebuffer; @@ -1463,11 +1089,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co bool reverse_cull = false; bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment); - if (render_buffer) { - screen_size.x = render_buffer->width; - screen_size.y = render_buffer->height; + if (rb.is_valid()) { + screen_size = rb->get_internal_size(); - if (render_buffer->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { + if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { color_pass_flags |= COLOR_PASS_FLAG_MOTION_VECTORS; } @@ -1495,17 +1120,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co switch (depth_pass_mode) { case PASS_MODE_DEPTH: { - depth_framebuffer = render_buffer->depth_fb; + depth_framebuffer = rb_data->get_depth_fb(); } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { - _allocate_normal_roughness_texture(render_buffer); - depth_framebuffer = render_buffer->depth_normal_roughness_fb; + depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS); depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { - _allocate_normal_roughness_texture(render_buffer); - render_buffer->ensure_voxelgi(); - depth_framebuffer = render_buffer->depth_normal_roughness_voxelgi_fb; + depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS_VOXELGI); depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); depth_pass_clear.push_back(Color(0, 0, 0, 0)); } break; @@ -1513,12 +1135,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co }; } - if (p_render_data->view_count > 1) { + if (p_render_data->scene_data->view_count > 1) { color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW; } - color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags); - color_only_framebuffer = render_buffer->color_only_fb; + color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags); + color_only_framebuffer = rb_data->get_color_only_fb(); } else if (p_render_data->reflection_probe.is_valid()) { uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; @@ -1537,20 +1159,17 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co ERR_FAIL(); //bug? } - scene_state.ubo.viewport_size[0] = screen_size.x; - scene_state.ubo.viewport_size[1] = screen_size.y; - - scene_state.ubo.emissive_exposure_normalization = -1.0; + p_render_data->scene_data->emissive_exposure_normalization = -1.0; RD::get_singleton()->draw_command_begin_label("Render Setup"); - _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->cam_transform); + _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); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) - _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_voxelgi); + _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, color_pass_flags, using_sdfgi, using_sdfgi || using_voxelgi); render_list[RENDER_LIST_OPAQUE].sort_by_key(); render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority(); _fill_instance_data(RENDER_LIST_OPAQUE, p_render_data->render_info ? p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE] : (int *)nullptr); @@ -1558,12 +1177,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_end_label(); - bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; + bool using_sss = rb_data.is_valid() && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; if (using_sss && !using_separate_specular) { using_separate_specular = true; color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR; - color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags); + color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags); } RID radiance_texture; bool draw_sky = false; @@ -1591,7 +1210,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 ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) { + if ((rb.is_valid() && 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())); } @@ -1601,7 +1220,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 ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_get_fog_enabled(p_render_data->environment)) { + if ((rb.is_valid() && 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())); } @@ -1624,20 +1243,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - Projection projection = p_render_data->cam_projection; + Projection projection = p_render_data->scene_data->cam_projection; if (p_render_data->reflection_probe.is_valid()) { Projection correction; correction.set_depth_correction(true); - projection = correction * p_render_data->cam_projection; + projection = correction * p_render_data->scene_data->cam_projection; } - sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->cam_transform, screen_size, this); + sky.setup(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this); sky_energy_multiplier *= bg_energy_multiplier; RID sky_rid = environment_get_sky(p_render_data->environment); if (sky_rid.is_valid()) { - sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, sky_energy_multiplier); + sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid @@ -1653,7 +1272,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 && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment); + bool using_ssao = depth_pre_pass && rb.is_valid() && 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 @@ -1676,7 +1295,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID()); bool finish_depth = using_ssao || using_sdfgi || using_voxelgi; - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_camera_plane, p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); _render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear); RD::get_singleton()->draw_command_end_label(); @@ -1685,19 +1304,19 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi); } - if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { + if (rb.is_valid() && 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) { if (needs_pre_resolve) { RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE); } - for (uint32_t v = 0; v < render_buffer->view_count; v++) { - resolve_effects->resolve_gi(render_buffer->depth_msaa_views[v], render_buffer->normal_roughness_msaa_views[v], using_voxelgi ? render_buffer->voxelgi_msaa_views[v] : RID(), render_buffer->depth_views[v], render_buffer->normal_roughness_views[v], using_voxelgi ? render_buffer->voxelgi_views[v] : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + resolve_effects->resolve_gi(rb_data->get_depth_msaa(v), rb_data->get_normal_roughness_msaa(v), using_voxelgi ? rb_data->get_voxelgi_msaa(v) : RID(), rb->get_depth_texture(v), rb_data->get_normal_roughness(v), using_voxelgi ? rb_data->get_voxelgi(v) : RID(), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]); } } else if (finish_depth) { - for (uint32_t v = 0; v < render_buffer->view_count; v++) { - resolve_effects->resolve_depth(render_buffer->depth_msaa_views[v], render_buffer->depth_views[v], Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + 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()]); } } RD::get_singleton()->draw_command_end_label(); @@ -1706,15 +1325,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co continue_depth = !finish_depth; } - RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; - _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : nullrids, render_buffer ? render_buffer->voxelgi_buffer : RID(), render_buffer ? render_buffer->vrs_views : nullrids); + RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS]; + if (rb_data.is_valid() && rb_data->has_normal_roughness()) { + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + normal_roughness_views[v] = rb_data->get_normal_roughness(v); + } + } + _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, normal_roughness_views, rb_data.is_valid() && rb_data->has_voxelgi() ? rb_data->get_voxelgi() : RID()); RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); - scene_state.ubo.directional_light_count = p_render_data->directional_light_count; - scene_state.ubo.opaque_prepass_threshold = 0.0f; + 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, p_render_data->render_buffers.is_valid()); + _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()); RENDER_TIMESTAMP("Render Opaque Pass"); @@ -1730,22 +1354,22 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co Vector<Color> c; { Color cc = clear_color.srgb_to_linear(); - if (using_separate_specular || render_buffer) { + if (using_separate_specular || rb_data.is_valid()) { cc.a = 0; //subsurf scatter must be 0 } c.push_back(cc); - if (render_buffer) { + if (rb_data.is_valid()) { c.push_back(Color(0, 0, 0, 0)); // Separate specular c.push_back(Color(0, 0, 0, 0)); // Motion vectors } } - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_camera_plane, p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); _render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); if (will_continue_color && using_separate_specular) { // close the specular framebuffer, as it's no longer used - RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); RD::get_singleton()->draw_list_end(); } } @@ -1759,7 +1383,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co Projection dc; dc.set_depth_correction(true); - Projection cm = (dc * p_render_data->cam_projection) * Projection(p_render_data->cam_transform.affine_inverse()); + Projection cm = (dc * p_render_data->scene_data->cam_projection) * Projection(p_render_data->scene_data->cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs"); for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) { @@ -1777,10 +1401,10 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co Projection dc; dc.set_depth_correction(true); Projection cms[RendererSceneRender::MAX_RENDER_VIEWS]; - for (uint32_t v = 0; v < p_render_data->view_count; v++) { - cms[v] = (dc * p_render_data->view_projection[v]) * Projection(p_render_data->cam_transform.affine_inverse()); + for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) { + cms[v] = (dc * p_render_data->scene_data->view_projection[v]) * Projection(p_render_data->scene_data->cam_transform.affine_inverse()); } - _debug_sdfgi_probes(p_render_data->render_buffers, color_only_framebuffer, p_render_data->view_count, cms, will_continue_color, will_continue_depth); + _debug_sdfgi_probes(rb, color_only_framebuffer, p_render_data->scene_data->view_count, cms, will_continue_color, will_continue_depth); } if (draw_sky || draw_sky_fog_only) { @@ -1791,29 +1415,29 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (p_render_data->reflection_probe.is_valid()) { Projection correction; correction.set_depth_correction(true); - Projection projection = correction * p_render_data->cam_projection; - sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier); + Projection projection = correction * p_render_data->scene_data->cam_projection; + sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); } else { - sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier); + sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); } RD::get_singleton()->draw_command_end_label(); } - if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { + if (rb.is_valid() && !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 < render_buffer->view_count; v++) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]); + 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)); } if (using_separate_specular) { - for (uint32_t v = 0; v < render_buffer->view_count; v++) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa_views[v], render_buffer->specular_views[v]); + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + RD::get_singleton()->texture_resolve_multisample(rb_data->get_specular_msaa(v), rb_data->get_specular(v)); } } } - if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - for (uint32_t v = 0; v < render_buffer->view_count; v++) { - resolve_effects->resolve_depth(render_buffer->depth_msaa_views[v], render_buffer->depth_views[v], Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + if (rb.is_valid() && !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()]); } } @@ -1821,19 +1445,23 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (using_sss) { RENDER_TIMESTAMP("Sub-Surface Scattering"); RD::get_singleton()->draw_command_begin_label("Process Sub-Surface Scattering"); - _process_sss(p_render_data->render_buffers, p_render_data->cam_projection); + _process_sss(rb, p_render_data->scene_data->cam_projection); RD::get_singleton()->draw_command_end_label(); } if (using_ssr) { RENDER_TIMESTAMP("Screen-Space Reflections"); RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections"); - _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_views, render_buffer->specular, render_buffer->specular_views, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->view_projection, p_render_data->view_eye_offset, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); + RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS]; + for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) { + specular_views[v] = rb_data->get_specular(v); + } + _process_ssr(rb, color_only_framebuffer, normal_roughness_views, rb_data->get_specular(), specular_views, p_render_data->environment, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, rb->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED); RD::get_singleton()->draw_command_end_label(); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - copy_effects->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID(), p_render_data->view_count); + copy_effects->merge_specular(color_only_framebuffer, rb_data->get_specular(), rb->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? RID() : rb->get_internal_texture(), RID(), p_render_data->scene_data->view_count); } } @@ -1857,8 +1485,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co { uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR); - RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_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(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + RID alpha_framebuffer = rb_data.is_valid() ? rb_data->get_color_pass_fb(transparent_color_pass_flags) : color_only_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(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_camera_plane, p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); } @@ -1868,13 +1496,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Resolve"); - if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - for (uint32_t v = 0; v < render_buffer->view_count; v++) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]); - resolve_effects->resolve_depth(render_buffer->depth_msaa_views[v], render_buffer->depth_views[v], Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { + 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)); + 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()]); } - if (render_buffer->use_taa) { // TODO make TAA stereo capable, this will need to be handled in a separate PR - RD::get_singleton()->texture_resolve_multisample(render_buffer->velocity_buffer_msaa, render_buffer->velocity_buffer); + if (taa && rb->get_use_taa()) { + taa->msaa_resolve(rb); } } @@ -1883,17 +1511,17 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Copy framebuffer for SSIL"); if (using_ssil) { RENDER_TIMESTAMP("Copy Final Framebuffer (SSIL)"); - _copy_framebuffer_to_ssil(p_render_data->render_buffers); + _copy_framebuffer_to_ssil(rb); } RD::get_singleton()->draw_command_end_label(); - if (render_buffer && render_buffer->use_taa) { + if (rb.is_valid() && taa && rb->get_use_taa()) { RENDER_TIMESTAMP("TAA") - _process_taa(p_render_data->render_buffers, render_buffer->velocity_buffer, p_render_data->z_near, p_render_data->z_far); + taa->process(rb, _render_buffers_get_color_format(), p_render_data->scene_data->z_near, p_render_data->scene_data->z_far); } - if (p_render_data->render_buffers.is_valid()) { - _debug_draw_cluster(p_render_data->render_buffers); + if (rb.is_valid()) { + _debug_draw_cluster(rb); RENDER_TIMESTAMP("Tonemap"); @@ -1915,34 +1543,36 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page SceneState::ShadowPass shadow_pass; + RenderSceneDataRD scene_data; + scene_data.cam_projection = p_projection; + scene_data.cam_transform = p_transform; + scene_data.view_projection[0] = p_projection; + scene_data.z_far = p_zfar; + scene_data.z_near = 0.0; + scene_data.lod_camera_plane = p_camera_plane; + scene_data.lod_distance_multiplier = p_lod_distance_multiplier; + scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; + scene_data.opaque_prepass_threshold = 0.1f; + RenderDataRD render_data; - render_data.cam_projection = p_projection; - render_data.cam_transform = p_transform; - render_data.view_projection[0] = p_projection; - render_data.z_far = p_zfar; - render_data.z_near = 0.0; + render_data.scene_data = &scene_data; render_data.cluster_size = 1; render_data.cluster_max_elements = 32; render_data.instances = &p_instances; - render_data.lod_camera_plane = p_camera_plane; - render_data.lod_distance_multiplier = p_lod_distance_multiplier; render_data.render_info = p_render_info; - scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; - scene_state.ubo.opaque_prepass_threshold = 0.1f; - _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index); if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { - render_data.screen_mesh_lod_threshold = 0.0; + scene_data.screen_mesh_lod_threshold = 0.0; } else { - render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; + scene_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; } PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW; uint32_t render_list_from = render_list[RENDER_LIST_SECONDARY].elements.size(); - _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, false, false, true); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, 0, false, false, true); uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from; render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size); _fill_instance_data(RENDER_LIST_SECONDARY, p_render_info ? p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW] : (int *)nullptr, render_list_from, render_list_size, false); @@ -1961,8 +1591,8 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete shadow_pass.camera_plane = p_camera_plane; - shadow_pass.screen_mesh_lod_threshold = render_data.screen_mesh_lod_threshold; - shadow_pass.lod_distance_multiplier = render_data.lod_distance_multiplier; + shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold; + shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; shadow_pass.framebuffer = p_framebuffer; shadow_pass.initial_depth_action = p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE : RD::INITIAL_ACTION_CONTINUE); @@ -2005,19 +1635,22 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); + RenderSceneDataRD scene_data; + scene_data.cam_projection = p_cam_projection; + scene_data.cam_transform = p_cam_transform; + scene_data.view_projection[0] = p_cam_projection; + scene_data.z_near = 0.0; + scene_data.z_far = p_cam_projection.get_z_far(); + scene_data.dual_paraboloid_side = 0; + scene_data.opaque_prepass_threshold = 0.0; + RenderDataRD render_data; - render_data.cam_projection = p_cam_projection; - render_data.cam_transform = p_cam_transform; - render_data.view_projection[0] = p_cam_projection; - render_data.z_near = 0.0; - render_data.z_far = p_cam_projection.get_z_far(); + render_data.scene_data = &scene_data; render_data.cluster_size = 1; render_data.cluster_max_elements = 32; render_data.instances = &p_instances; _update_render_base_uniform_set(); - scene_state.ubo.dual_paraboloid_side = 0; - scene_state.ubo.opaque_prepass_threshold = 0.0; _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); @@ -2044,21 +1677,23 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform RD::get_singleton()->draw_command_begin_label("Render 3D Material"); + RenderSceneDataRD scene_data; + scene_data.cam_projection = p_cam_projection; + scene_data.cam_transform = p_cam_transform; + scene_data.view_projection[0] = p_cam_projection; + scene_data.dual_paraboloid_side = 0; + scene_data.material_uv2_mode = false; + scene_data.opaque_prepass_threshold = 0.0f; + scene_data.emissive_exposure_normalization = p_exposure_normalization; + RenderDataRD render_data; - render_data.cam_projection = p_cam_projection; - render_data.cam_transform = p_cam_transform; - render_data.view_projection[0] = p_cam_projection; + render_data.scene_data = &scene_data; render_data.cluster_size = 1; render_data.cluster_max_elements = 32; render_data.instances = &p_instances; _update_render_base_uniform_set(); - scene_state.ubo.dual_paraboloid_side = 0; - scene_state.ubo.material_uv2_mode = false; - scene_state.ubo.opaque_prepass_threshold = 0.0f; - scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization; - _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; @@ -2094,18 +1729,20 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance RD::get_singleton()->draw_command_begin_label("Render UV2"); + RenderSceneDataRD scene_data; + scene_data.dual_paraboloid_side = 0; + scene_data.material_uv2_mode = true; + scene_data.opaque_prepass_threshold = 0.0; + scene_data.emissive_exposure_normalization = -1.0; + RenderDataRD render_data; + render_data.scene_data = &scene_data; render_data.cluster_size = 1; render_data.cluster_max_elements = 32; render_data.instances = &p_instances; _update_render_base_uniform_set(); - scene_state.ubo.dual_paraboloid_side = 0; - scene_state.ubo.material_uv2_mode = true; - scene_state.ubo.opaque_prepass_threshold = 0.0; - scene_state.ubo.emissive_exposure_normalization = -1.0; - _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; @@ -2160,21 +1797,21 @@ void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance RD::get_singleton()->draw_command_end_label(); } -void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) { +void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) { RENDER_TIMESTAMP("Render SDFGI"); RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel"); + RenderSceneDataRD scene_data; + RenderDataRD render_data; + render_data.scene_data = &scene_data; render_data.cluster_size = 1; render_data.cluster_max_elements = 32; render_data.instances = &p_instances; _update_render_base_uniform_set(); - RenderBufferDataForwardClustered *render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); - ERR_FAIL_COND(!render_buffer); - PassMode pass_mode = PASS_MODE_SDF; _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); @@ -2209,26 +1846,26 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i fb_size.x = p_size[right_axis]; fb_size.y = p_size[up_axis]; - render_data.cam_transform.origin = center + axis * half_extents; - render_data.cam_transform.basis.set_column(0, right); - render_data.cam_transform.basis.set_column(1, up); - render_data.cam_transform.basis.set_column(2, axis); + scene_data.cam_transform.origin = center + axis * half_extents; + scene_data.cam_transform.basis.set_column(0, right); + scene_data.cam_transform.basis.set_column(1, up); + scene_data.cam_transform.basis.set_column(2, axis); - //print_line("pass: " + itos(i) + " xform " + render_data.cam_transform); + //print_line("pass: " + itos(i) + " xform " + scene_data.cam_transform); float h_size = half_extents[right_axis]; float v_size = half_extents[up_axis]; float d_size = half_extents[i] * 2.0; - render_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size); + scene_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size); //print_line("pass: " + itos(i) + " cam hsize: " + rtos(h_size) + " vsize: " + rtos(v_size) + " dsize " + rtos(d_size)); Transform3D to_bounds; to_bounds.origin = p_bounds.position; to_bounds.basis.scale(p_bounds.size); - RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds); + RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * scene_data.cam_transform, scene_state.ubo.sdf_to_bounds); - scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization; + scene_data.emissive_exposure_normalization = p_exposure_normalization; _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture); @@ -2449,9 +2086,11 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - RenderBufferDataForwardClustered *rb = nullptr; + Ref<RenderSceneBuffersRD> rb; // handy for not having to fully type out p_render_data->render_buffers all the time... + Ref<RenderBufferDataForwardClustered> rb_data; if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); + rb = p_render_data->render_buffers; + rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); } //default render buffer and scene state uniform set @@ -2468,6 +2107,13 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend { RD::Uniform u; u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.append_id(scene_state.implementation_uniform_buffers[p_index]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID instance_buffer = scene_state.instance_buffer[p_render_list]; if (instance_buffer == RID()) { @@ -2484,16 +2130,15 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } RD::Uniform u; - u.binding = 2; + u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.append_id(radiance_texture); uniforms.push_back(u); } - { RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID(); RD::Uniform u; - u.binding = 3; + u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (ref_texture.is_valid()) { u.append_id(ref_texture); @@ -2502,10 +2147,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } uniforms.push_back(u); } - { RD::Uniform u; - u.binding = 4; + u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture; if (p_render_data && p_render_data->shadow_atlas.is_valid()) { @@ -2519,7 +2163,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } { RD::Uniform u; - u.binding = 5; + u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { u.append_id(directional_shadow_get_texture()); @@ -2530,7 +2174,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } { RD::Uniform u; - u.binding = 6; + u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); @@ -2549,7 +2193,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } { RD::Uniform u; - u.binding = 7; + u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) { @@ -2569,7 +2213,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend { RD::Uniform u; - u.binding = 8; + u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID cb = (p_render_data && p_render_data->cluster_buffer.is_valid()) ? p_render_data->cluster_buffer : scene_shader.default_vec4_xform_buffer; u.append_id(cb); @@ -2578,118 +2222,130 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend { RD::Uniform u; - u.binding = 9; + u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); + RID texture; + if (rb.is_valid() && rb->has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH)) { + texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH); + } else { + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); + } u.append_id(texture); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 10; + u.binding = 11; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); + RID bbt = rb_data.is_valid() ? rb->get_back_buffer_texture() : RID(); RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); } { - { - RD::Uniform u; - u.binding = 11; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); - u.append_id(texture); - uniforms.push_back(u); - } + RD::Uniform u; + u.binding = 12; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb_data.is_valid() && rb_data->has_normal_roughness() ? rb_data->get_normal_roughness() : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_NORMAL); + u.append_id(texture); + uniforms.push_back(u); + } - { - RD::Uniform u; - u.binding = 12; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID(); - RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); - u.append_id(texture); - uniforms.push_back(u); - } + { + RD::Uniform u; + u.binding = 13; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID aot = rb_data.is_valid() ? rb->get_ao_texture() : RID(); + RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + u.append_id(texture); + uniforms.push_back(u); + } - { - RD::Uniform u; - u.binding = 13; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID(); - RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); - u.append_id(texture); - uniforms.push_back(u); - } + { + RD::Uniform u; + u.binding = 14; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb_data.is_valid() && rb->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT) ? rb->get_texture(RB_SCOPE_GI, RB_TEX_AMBIENT) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + u.append_id(texture); + uniforms.push_back(u); + } - { - RD::Uniform u; - u.binding = 14; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID(); - RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); - u.append_id(texture); - uniforms.push_back(u); + { + RD::Uniform u; + u.binding = 15; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb_data.is_valid() && rb->has_texture(RB_SCOPE_GI, RB_TEX_REFLECTION) ? rb->get_texture(RB_SCOPE_GI, RB_TEX_REFLECTION) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + u.append_id(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 16; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID t; + if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + t = sdfgi->lightprobe_texture; } - { - RD::Uniform u; - u.binding = 15; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID t; - if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { - t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers); - } else { - t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); - } - u.append_id(t); - uniforms.push_back(u); + if (t.is_null()) { + t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } - { - RD::Uniform u; - u.binding = 16; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { - u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE)); - } - uniforms.push_back(u); + u.append_id(t); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 17; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID t; + if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + t = sdfgi->occlusion_texture; } - { - RD::Uniform u; - u.binding = 17; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer()); - uniforms.push_back(u); + if (t.is_null()) { + t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } - { - RD::Uniform u; - u.binding = 18; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID vfog = RID(); - if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { - vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers); - if (vfog.is_null()) { - vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); - } - } else { + u.append_id(t); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 18; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + RID voxel_gi; + if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_GI)) { + Ref<RendererRD::GI::RenderBuffersGI> rbgi = rb->get_custom_data(RB_SCOPE_GI); + voxel_gi = rbgi->get_voxel_gi_buffer(); + } + u.append_id(voxel_gi.is_valid() ? voxel_gi : render_buffers_get_default_voxel_gi_buffer()); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 19; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID vfog = RID(); + if (rb_data.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = rb->get_custom_data(RB_SCOPE_FOG); + vfog = fog->fog_map; + if (vfog.is_null()) { vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } - u.append_id(vfog); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 19; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID(); - RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); - u.append_id(texture); - uniforms.push_back(u); + } else { + vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); } + u.append_id(vfog); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 20; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + RID ssil = rb_data.is_valid() ? rb->get_ssil_texture() : RID(); + RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); + u.append_id(texture); + uniforms.push_back(u); } return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET, uniforms); @@ -2709,6 +2365,13 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { RD::Uniform u; u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.append_id(scene_state.implementation_uniform_buffers[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID instance_buffer = scene_state.instance_buffer[RENDER_LIST_SECONDARY]; if (instance_buffer == RID()) { @@ -2721,7 +2384,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te // No radiance texture. RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); RD::Uniform u; - u.binding = 2; + u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.append_id(radiance_texture); uniforms.push_back(u); @@ -2731,7 +2394,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te // No reflection atlas. RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); RD::Uniform u; - u.binding = 3; + u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.append_id(ref_texture); uniforms.push_back(u); @@ -2740,7 +2403,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No shadow atlas. RD::Uniform u; - u.binding = 4; + u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); @@ -2750,7 +2413,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No directional shadow atlas. RD::Uniform u; - u.binding = 5; + u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); u.append_id(texture); @@ -2760,7 +2423,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No Lightmaps RD::Uniform u; - u.binding = 6; + u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); @@ -2774,7 +2437,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { // No VoxelGIs RD::Uniform u; - u.binding = 7; + u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE); @@ -2787,7 +2450,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { RD::Uniform u; - u.binding = 8; + u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; RID cb = scene_shader.default_vec4_xform_buffer; u.append_id(cb); @@ -2799,28 +2462,28 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 9; + u.binding = 10; u.append_id(p_albedo_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 10; + u.binding = 11; u.append_id(p_emission_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 11; + u.binding = 12; u.append_id(p_emission_aniso_texture); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 12; + u.binding = 13; u.append_id(p_geom_facing_texture); uniforms.push_back(u); } @@ -2828,16 +2491,14 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET, uniforms); } -RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { - RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); +RID RenderForwardClustered::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) { + Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED); - return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->normal_roughness_buffer : rb->normal_roughness_buffer_msaa; + return p_render_buffers->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? rb_data->get_normal_roughness() : rb_data->get_normal_roughness_msaa(); } -RID RenderForwardClustered::_render_buffers_get_velocity_texture(RID p_render_buffers) { - RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); - - return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->velocity_buffer : rb->velocity_buffer_msaa; +RID RenderForwardClustered::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) { + return p_render_buffers->get_velocity_buffer(p_render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED); } RenderForwardClustered *RenderForwardClustered::singleton = nullptr; @@ -3383,9 +3044,15 @@ RenderForwardClustered::RenderForwardClustered() { _update_shader_quality_settings(); resolve_effects = memnew(RendererRD::Resolve()); + taa = memnew(RendererRD::TAA); } RenderForwardClustered::~RenderForwardClustered() { + if (taa != nullptr) { + memdelete(taa); + taa = nullptr; + } + if (resolve_effects != nullptr) { memdelete(resolve_effects); resolve_effects = nullptr; @@ -3397,6 +3064,9 @@ RenderForwardClustered::~RenderForwardClustered() { for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) { RD::get_singleton()->free(scene_state.uniform_buffers[i]); } + for (uint32_t i = 0; i < scene_state.implementation_uniform_buffers.size(); i++) { + RD::get_singleton()->free(scene_state.implementation_uniform_buffers[i]); + } RD::get_singleton()->free(scene_state.lightmap_buffer); RD::get_singleton()->free(scene_state.lightmap_capture_buffer); for (uint32_t i = 0; i < RENDER_LIST_MAX; i++) { diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 3d74f6769e..605473ad0b 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -33,12 +33,22 @@ #include "core/templates/paged_allocator.h" #include "servers/rendering/renderer_rd/effects/resolve.h" +#include "servers/rendering/renderer_rd/effects/taa.h" #include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/utilities.h" +#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered") + +#define RB_TEX_SPECULAR SNAME("specular") +#define RB_TEX_SPECULAR_MSAA SNAME("specular_msaa") +#define RB_TEX_ROUGHNESS SNAME("normal_roughnesss") +#define RB_TEX_ROUGHNESS_MSAA SNAME("normal_roughnesss_msaa") +#define RB_TEX_VOXEL_GI SNAME("voxel_gi") +#define RB_TEX_VOXEL_GI_MSAA SNAME("voxel_gi_msaa") + namespace RendererSceneRenderImplementation { class RenderForwardClustered : public RendererSceneRenderRD { @@ -81,73 +91,67 @@ class RenderForwardClustered : public RendererSceneRenderRD { /* Framebuffer */ - struct RenderBufferDataForwardClustered : public RenderBufferData { - //for rendering, may be MSAAd - - RID color; - RID depth; - RID specular; - RID normal_roughness_buffer; - RID voxelgi_buffer; - RID velocity_buffer; + class RenderBufferDataForwardClustered : public RenderBufferCustomDataRD { + GDCLASS(RenderBufferDataForwardClustered, RenderBufferCustomDataRD) - RS::ViewportMSAA msaa; - RD::TextureSamples texture_samples; - bool use_taa; + private: + RenderSceneBuffersRD *render_buffers = nullptr; + RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1; - RID color_msaa; - RID depth_msaa; - RID specular_msaa; - RID normal_roughness_buffer_msaa; - RID voxelgi_buffer_msaa; - RID velocity_buffer_msaa; + public: + //for rendering, may be MSAAd - RID depth_fb; - RID depth_normal_roughness_fb; - RID depth_normal_roughness_voxelgi_fb; - RID color_only_fb; - RID specular_only_fb; + enum DepthFrameBufferType { + DEPTH_FB, + DEPTH_FB_ROUGHNESS, + DEPTH_FB_ROUGHNESS_VOXELGI + }; - RID vrs; + RID render_sdfgi_uniform_set; - int width, height; - HashMap<uint32_t, RID> color_framebuffers; + RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA); } + RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA, p_layer, 0); } - // for multiview - uint32_t view_count = 1; - RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this - RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this - RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; - RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA); } + RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, p_layer, 0); } - RID render_sdfgi_uniform_set; void ensure_specular(); + bool has_specular() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); } + RID get_specular() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); } + RID get_specular(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR, p_layer, 0); } + RID get_specular_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, p_layer, 0); } + + void ensure_normal_roughness_texture(); + bool has_normal_roughness() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); } + RID get_normal_roughness() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); } + RID get_normal_roughness(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, p_layer, 0); } + RID get_normal_roughness_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA); } + RID get_normal_roughness_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, p_layer, 0); } + void ensure_voxelgi(); - void ensure_velocity(); - void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); + bool has_voxelgi() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); } + RID get_voxelgi() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); } + RID get_voxelgi(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, p_layer, 0); } + RID get_voxelgi_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, p_layer, 0); } + + RID get_color_only_fb(); RID get_color_pass_fb(uint32_t p_color_pass_flags); + RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB); + RID get_specular_only_fb(); - ~RenderBufferDataForwardClustered(); + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; + virtual void free_data() override; }; - virtual RenderBufferData *_create_render_buffer_data() override; - void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb); + virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override; RID render_base_uniform_set; uint64_t lightmap_texture_array_version = 0xFFFFFFFF; virtual void _base_uniforms_changed() override; - virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override; - virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override; + virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; bool base_uniform_set_updated = false; void _update_render_base_uniform_set(); @@ -245,61 +249,22 @@ class RenderForwardClustered : public RendererSceneRenderRD { }; struct SceneState { - // This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code + // This struct is loaded into Set 1 - Binding 1, populated at start of rendering a frame, must match with shader code struct UBO { - float projection_matrix[16]; - float inv_projection_matrix[16]; - float inv_view_matrix[16]; - float view_matrix[16]; - - float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; - float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; - float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4]; - - float viewport_size[2]; - float screen_pixel_size[2]; - uint32_t cluster_shift; uint32_t cluster_width; uint32_t cluster_type_size; uint32_t max_cluster_element_count_div_32; - float directional_penumbra_shadow_kernel[128]; //32 vec4s - float directional_soft_shadow_kernel[128]; - float penumbra_shadow_kernel[128]; - float soft_shadow_kernel[128]; - - float ambient_light_color_energy[4]; - - float ambient_color_sky_mix; - uint32_t use_ambient_light; - uint32_t use_ambient_cubemap; - uint32_t use_reflection_cubemap; - - float radiance_inverse_xform[12]; - - float shadow_atlas_pixel_size[2]; - float directional_shadow_pixel_size[2]; - - uint32_t directional_light_count; - float dual_paraboloid_side; - float z_far; - float z_near; - uint32_t ss_effects_flags; float ssao_light_affect; float ssao_ao_affect; - uint32_t roughness_limiter_enabled; - - float roughness_limiter_amount; - float roughness_limiter_limit; - float opaque_prepass_threshold; - uint32_t roughness_limiter_pad; + uint32_t pad1; float sdf_to_bounds[16]; int32_t sdf_offset[3]; - uint32_t material_uv2_mode; + uint32_t pad2; int32_t sdf_size[3]; uint32_t gi_upscale_for_msaa; @@ -308,32 +273,13 @@ class RenderForwardClustered : public RendererSceneRenderRD { float volumetric_fog_inv_length; float volumetric_fog_detail_spread; uint32_t volumetric_fog_pad; - - // Fog - uint32_t fog_enabled; - float fog_density; - float fog_height; - float fog_height_density; - - float fog_light_color[3]; - float fog_sun_scatter; - - float fog_aerial_perspective; - - float time; - float reflection_multiplier; - - uint32_t pancake_shadows; - - float taa_jitter[2]; - float emissive_exposure_normalization; // Needed to normalize emissive when using physical units. - float IBL_exposure_normalization; }; struct PushConstant { uint32_t base_index; // uint32_t uv_offset; //packed - uint32_t pad[2]; + uint32_t multimesh_motion_vectors_current_offset; + uint32_t multimesh_motion_vectors_previous_offset; }; struct InstanceData { @@ -346,11 +292,10 @@ class RenderForwardClustered : public RendererSceneRenderRD { float lightmap_uv_scale[4]; }; - UBO ubo_data[2]; - UBO &ubo = ubo_data[0]; - UBO &prev_ubo = ubo_data[1]; + UBO ubo; LocalVector<RID> uniform_buffers; + LocalVector<RID> implementation_uniform_buffers; LightmapData lightmaps[MAX_LIGHTMAPS]; RID lightmap_ids[MAX_LIGHTMAPS]; @@ -425,7 +370,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _update_instance_data_buffer(RenderListType p_render_list); void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); - void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false); + void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false); HashMap<Size2i, RID> sdfgi_framebuffer_size_cache; @@ -612,6 +557,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { virtual void _update_shader_quality_settings() override; RendererRD::Resolve *resolve_effects = nullptr; + RendererRD::TAA *taa = nullptr; protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; @@ -623,7 +569,7 @@ protected: virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; + virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; public: diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 0911ee595f..75ccf1add5 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 @@ -375,7 +375,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void SceneShaderForwardClustered::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -448,7 +448,7 @@ void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<Rende } } -bool SceneShaderForwardClustered::ShaderData::is_param_texture(const StringName &p_param) const { +bool SceneShaderForwardClustered::ShaderData::is_parameter_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h index d6b526fa4a..a9a9fa94de 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h @@ -32,7 +32,7 @@ #define SCENE_SHADER_FORWARD_CLUSTERED_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl.gen.h" namespace RendererSceneRenderImplementation { @@ -182,11 +182,11 @@ public: virtual void set_code(const String &p_Code); virtual void set_path_hint(const String &p_path); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; virtual Variant get_default_parameter(const StringName &p_parameter) const; 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 67d001dcb7..a6512497a3 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -69,183 +69,175 @@ void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id, /* Render buffer */ -void RenderForwardMobile::RenderBufferDataForwardMobile::clear() { - if (color_msaa.is_valid()) { - RD::get_singleton()->free(color_msaa); - color_msaa = RID(); +void RenderForwardMobile::RenderBufferDataForwardMobile::free_data() { + // this should already be done but JIC.. + if (render_buffers) { + render_buffers->clear_context(RB_SCOPE_MOBILE); } +} - if (depth_msaa.is_valid()) { - RD::get_singleton()->free(depth_msaa); - depth_msaa = RID(); +void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBuffersRD *p_render_buffers) { + if (render_buffers) { + // JIC + free_data(); } - color = RID(); - depth = RID(); - for (int i = 0; i < FB_CONFIG_MAX; i++) { - color_fbs[i] = RID(); - } -} + render_buffers = p_render_buffers; + ERR_FAIL_NULL(render_buffers); // Huh? really? -void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { - clear(); + RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d(); + if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) { + // Create our MSAA textures... - msaa = p_msaa; - vrs = p_vrs_texture; + RD::DataFormat format = render_buffers->get_base_data_format(); + uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer); + const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { + RD::TEXTURE_SAMPLES_1, + RD::TEXTURE_SAMPLES_2, + RD::TEXTURE_SAMPLES_4, + RD::TEXTURE_SAMPLES_8, + }; - width = p_width; - height = p_height; - bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height); - view_count = p_view_count; + texture_samples = ts[msaa_3d]; - color = p_color_buffer; - depth = p_depth_buffer; + render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples); - // We are creating 4 configurations here for our framebuffers. + format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) { - Vector<RID> fb; - fb.push_back(p_color_buffer); // 0 - color buffer - fb.push_back(depth); // 1 - depth buffer - if (vrs.is_valid()) { - fb.push_back(vrs); // 2 - vrs texture - } + render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples); + } +} - // Now define our subpasses - Vector<RD::FramebufferPass> passes; - RD::FramebufferPass pass; +RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) { + ERR_FAIL_NULL_V(render_buffers, RID()); - // re-using the same attachments - pass.color_attachments.push_back(0); - pass.depth_attachment = 1; - if (vrs.is_valid()) { - pass.vrs_attachment = 2; - } + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_NULL_V(texture_storage, RID()); - // - opaque pass - passes.push_back(pass); - color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); + // We use our framebuffer cache here instead of building these in RenderBufferDataForwardMobile::configure + // This approach ensures we only build the framebuffers we actually need for this viewport. + // In the (near) future this means that if we cycle through a texture chain for our render target, we'll also support + // this. - // - add sky pass - passes.push_back(pass); - color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); + RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d(); + bool use_msaa = msaa_3d != RS::VIEWPORT_MSAA_DISABLED; - // - add alpha pass - passes.push_back(pass); - color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); + uint32_t view_count = render_buffers->get_view_count(); - if (!is_scaled) { - // - add blit to 2D pass - int target_buffer_id = fb.size(); - fb.push_back(p_target_buffer); // 2/3 - target buffer + RID vrs_texture; + if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) { + vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE); + } - RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(target_buffer_id); - blit_pass.input_attachments.push_back(0); - passes.push_back(blit_pass); // this doesn't need VRS + Vector<RID> textures; + int color_buffer_id = 0; + textures.push_back(use_msaa ? get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer + textures.push_back(use_msaa ? get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer + if (vrs_texture.is_valid()) { + textures.push_back(vrs_texture); // 2 - vrs texture + } + if (use_msaa) { + color_buffer_id = textures.size(); + textures.push_back(render_buffers->get_internal_texture()); // color buffer for resolve - color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); - } else { - // can't do our blit pass if resolutions don't match - color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID(); - } - } else { - RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format(); + // TODO add support for resolving depth buffer!!! + } - RD::TextureFormat tf; - if (view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - } else { - tf.texture_type = RD::TEXTURE_TYPE_2D; - } - tf.format = color_format; - tf.width = p_width; - tf.height = p_height; - tf.array_layers = view_count; // create a layer for every view - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + // Now define our subpasses + Vector<RD::FramebufferPass> passes; - const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { - RD::TEXTURE_SAMPLES_1, - RD::TEXTURE_SAMPLES_2, - RD::TEXTURE_SAMPLES_4, - RD::TEXTURE_SAMPLES_8, - }; + // Define our base pass, we'll be re-using this + RD::FramebufferPass pass; + pass.color_attachments.push_back(0); + pass.depth_attachment = 1; + if (vrs_texture.is_valid()) { + pass.vrs_attachment = 2; + } + + switch (p_config_type) { + case FB_CONFIG_ONE_PASS: { + // just one pass + if (use_msaa) { + // Add resolve + pass.resolve_attachments.push_back(color_buffer_id); + } + passes.push_back(pass); - texture_samples = ts[p_msaa]; - tf.samples = texture_samples; + return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count); + } break; + case FB_CONFIG_TWO_SUBPASSES: { + // - opaque pass + passes.push_back(pass); - color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + // - add sky pass + if (use_msaa) { + // add resolve + pass.resolve_attachments.push_back(color_buffer_id); + } + passes.push_back(pass); - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count); + } break; + case FB_CONFIG_THREE_SUBPASSES: { + // - opaque pass + passes.push_back(pass); - depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + // - add sky pass + passes.push_back(pass); - { - Vector<RID> fb; - fb.push_back(color_msaa); // 0 - msaa color buffer - fb.push_back(depth_msaa); // 1 - msaa depth buffer - if (vrs.is_valid()) { - fb.push_back(vrs); // 2 - vrs texture + // - add alpha pass + if (use_msaa) { + // add resolve + pass.resolve_attachments.push_back(color_buffer_id); } + passes.push_back(pass); - // Now define our subpasses - Vector<RD::FramebufferPass> passes; - RD::FramebufferPass pass; + return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count); + } break; + case FB_CONFIG_FOUR_SUBPASSES: { + Size2i target_size = render_buffers->get_target_size(); + Size2i internal_size = render_buffers->get_internal_size(); - // re-using the same attachments - pass.color_attachments.push_back(0); - pass.depth_attachment = 1; - if (vrs.is_valid()) { - pass.vrs_attachment = 2; - } + // can't do our blit pass if resolutions don't match + ERR_FAIL_COND_V(target_size != internal_size, RID()); // - opaque pass passes.push_back(pass); // - add sky pass - int color_buffer_id = fb.size(); - fb.push_back(color); // color buffer - passes.push_back(pass); // without resolve for our 3 + 4 subpass config - { - // but with resolve for our 2 subpass config - Vector<RD::FramebufferPass> two_passes; - two_passes.push_back(pass); // opaque subpass without resolve - pass.resolve_attachments.push_back(color_buffer_id); - two_passes.push_back(pass); // sky subpass with resolve + passes.push_back(pass); - color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count); + // - add alpha pass + if (use_msaa) { + // add resolve + pass.resolve_attachments.push_back(color_buffer_id); } - - // - add alpha pass (with resolve, we just added that above) passes.push_back(pass); - color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); - { - // we also need our one pass with resolve - Vector<RD::FramebufferPass> one_pass_with_resolve; - one_pass_with_resolve.push_back(pass); // note our pass configuration already has resolve.. - color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count); - } + // - add blit to 2D pass + RID render_target = render_buffers->get_render_target(); + ERR_FAIL_COND_V(render_target.is_null(), RID()); + RID target_buffer = texture_storage->render_target_get_rd_texture(render_target); + ERR_FAIL_COND_V(target_buffer.is_null(), RID()); - if (!is_scaled) { - // - add blit to 2D pass - int target_buffer_id = fb.size(); - fb.push_back(p_target_buffer); // target buffer - RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(target_buffer_id); - blit_pass.input_attachments.push_back(color_buffer_id); - passes.push_back(blit_pass); + int target_buffer_id = textures.size(); + textures.push_back(target_buffer); // target buffer - color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); - } else { - // can't do our blit pass if resolutions don't match - color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID(); - } - } - } + RD::FramebufferPass blit_pass; + blit_pass.input_attachments.push_back(color_buffer_id); // Read from our (resolved) color buffer + blit_pass.color_attachments.push_back(target_buffer_id); // Write into our target buffer + // this doesn't need VRS + passes.push_back(blit_pass); + + return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count); + } break; + default: + break; + }; + + return RID(); } RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_depth) { @@ -274,12 +266,11 @@ RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_ return RD::get_singleton()->framebuffer_create_multipass(fb, passes); } -RenderForwardMobile::RenderBufferDataForwardMobile::~RenderBufferDataForwardMobile() { - clear(); -} +void RenderForwardMobile::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) { + Ref<RenderBufferDataForwardMobile> data; + data.instantiate(); -RendererSceneRenderRD::RenderBufferData *RenderForwardMobile::_create_render_buffer_data() { - return memnew(RenderBufferDataForwardMobile); + p_render_buffers->set_custom_data(RB_SCOPE_MOBILE, data); } bool RenderForwardMobile::free(RID p_rid) { @@ -314,9 +305,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ //there should always be enough uniform buffers for render passes, otherwise bugs ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID()); - RenderBufferDataForwardMobile *rb = nullptr; + Ref<RenderBufferDataForwardMobile> rb_data; + Ref<RenderSceneBuffersRD> rb; if (p_render_data && p_render_data->render_buffers.is_valid()) { - rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); + rb = p_render_data->render_buffers; + rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); } // default render buffer and scene state uniform set @@ -442,8 +435,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 9; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID(); - RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); + RID texture; + if (rb.is_valid() && rb->has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH)) { + texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH); + } else { + texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); + } u.append_id(texture); uniforms.push_back(u); } @@ -451,7 +448,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); + RID bbt = rb_data.is_valid() ? rb->get_back_buffer_texture() : RID(); RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); u.append_id(texture); uniforms.push_back(u); @@ -500,15 +497,27 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co } void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { - RenderBufferDataForwardMobile *render_buffer = nullptr; + Ref<RenderBufferDataForwardMobile> rb_data; if (p_render_data->render_buffers.is_valid()) { - render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); + rb_data = p_render_data->render_buffers->get_custom_data(RB_SCOPE_MOBILE); } RENDER_TIMESTAMP("Setup 3D Scene"); - scene_state.ubo.directional_light_count = 0; - scene_state.ubo.opaque_prepass_threshold = 0.0; + /* TODO + // 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 (render target has velocity override) { // TODO + p_render_data->scene_data->calculate_motion_vectors = true; + } else { + p_render_data->scene_data->calculate_motion_vectors = false; + } + */ + p_render_data->scene_data->calculate_motion_vectors = false; // for now, not yet supported... + + p_render_data->scene_data->directional_light_count = 0; + p_render_data->scene_data->opaque_prepass_threshold = 0.0; // We can only use our full subpass approach if we're: // - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE @@ -538,12 +547,11 @@ 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 (render_buffer) { + if (rb_data.is_valid()) { // setup rendering to render buffer - screen_size.x = render_buffer->width; - screen_size.y = render_buffer->height; + screen_size = p_render_data->render_buffers->get_internal_size(); - if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) { + if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) { // can't do blit subpass using_subpass_post_process = false; } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || 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))) { @@ -559,13 +567,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (using_subpass_post_process) { // all as subpasses - framebuffer = render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES]; + framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES); } else if (using_subpass_transparent) { // our tonemap pass is separate - framebuffer = render_buffer->color_fbs[FB_CONFIG_THREE_SUBPASSES]; + framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_THREE_SUBPASSES); } else { // only opaque and sky as subpasses - framebuffer = render_buffer->color_fbs[FB_CONFIG_TWO_SUBPASSES]; + framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES); } } else if (p_render_data->reflection_probe.is_valid()) { uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe); @@ -585,13 +593,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color ERR_FAIL(); //bug? } - scene_state.ubo.viewport_size[0] = screen_size.x; - scene_state.ubo.viewport_size[1] = screen_size.y; - scene_state.ubo.emissive_exposure_normalization = -1.0; + p_render_data->scene_data->emissive_exposure_normalization = -1.0; RD::get_singleton()->draw_command_begin_label("Render Setup"); - _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->cam_transform); + _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); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) @@ -626,7 +632,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; /* - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) { + if (p_render_data->render_buffers->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())); } @@ -638,7 +644,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color clear_color.g *= bg_energy_multiplier; clear_color.b *= bg_energy_multiplier; /* - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) { + if (p_render_data->render_buffers->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())); } @@ -662,20 +668,20 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) { RENDER_TIMESTAMP("Setup Sky"); RD::get_singleton()->draw_command_begin_label("Setup Sky"); - Projection projection = p_render_data->cam_projection; + Projection projection = p_render_data->scene_data->cam_projection; if (p_render_data->reflection_probe.is_valid()) { Projection correction; correction.set_depth_correction(true); - projection = correction * p_render_data->cam_projection; + projection = correction * p_render_data->scene_data->cam_projection; } - sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->cam_transform, screen_size, this); + sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this); sky_energy_multiplier *= bg_energy_multiplier; RID sky_rid = environment_get_sky(p_render_data->environment); if (sky_rid.is_valid()) { - sky.update(p_render_data->environment, projection, p_render_data->cam_transform, time, sky_energy_multiplier); + sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid @@ -698,17 +704,17 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (p_render_data->reflection_probe.is_valid()) { Projection correction; correction.set_depth_correction(true); - Projection projection = correction * p_render_data->cam_projection; - sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier); + Projection projection = correction * p_render_data->scene_data->cam_projection; + sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); } else { - sky.update_res_buffers(p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier); + sky.update_res_buffers(p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); } RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; - _pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids); + _pre_opaque_render(p_render_data, false, false, false, nullrids, RID()); uint32_t spec_constant_base_flags = 0; @@ -728,7 +734,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } } { - if (render_buffer) { + if (rb_data.is_valid()) { RD::get_singleton()->draw_command_begin_label("Render 3D Pass"); } else { RD::get_singleton()->draw_command_begin_label("Render Reflection Probe Pass"); @@ -738,7 +744,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_begin_label("Render Opaque Subpass"); - scene_state.ubo.directional_light_count = p_render_data->directional_light_count; + 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()); @@ -759,8 +765,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // regular forward for now Vector<Color> c; c.push_back(clear_color.srgb_to_linear()); // our render buffer - if (render_buffer) { - if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { + if (rb_data.is_valid()) { + if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) { c.push_back(clear_color.srgb_to_linear()); // our resolve buffer } if (using_subpass_post_process) { @@ -769,7 +775,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].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->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].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_camera_plane, p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -797,10 +803,10 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (p_render_data->reflection_probe.is_valid()) { Projection correction; correction.set_depth_correction(true); - Projection projection = correction * p_render_data->cam_projection; - sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->cam_transform, time, sky_energy_multiplier); + Projection projection = correction * p_render_data->scene_data->cam_projection; + sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); } else { - sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, sky_energy_multiplier); + sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier); } RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass @@ -836,7 +842,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (using_subpass_transparent) { 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_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + 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_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_camera_plane, p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -859,8 +865,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color // note if we are using MSAA we should get an automatic resolve through our subpass configuration. // blit to tonemap - if (render_buffer && using_subpass_post_process) { - _post_process_subpass(render_buffer->color, framebuffer, p_render_data); + if (rb_data.is_valid() && using_subpass_post_process) { + _post_process_subpass(p_render_data->render_buffers->get_internal_texture(), framebuffer, p_render_data); } RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass @@ -869,13 +875,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } else { RENDER_TIMESTAMP("Render Transparent"); - framebuffer = render_buffer->color_fbs[FB_CONFIG_ONE_PASS]; + framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS); // 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); 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->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); + 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_camera_plane, p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count); render_list_params.framebuffer_format = fb_format; if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time @@ -897,7 +903,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color } } - if (render_buffer && !using_subpass_post_process) { + if (rb_data.is_valid() && !using_subpass_post_process) { RD::get_singleton()->draw_command_begin_label("Post process pass"); // If we need extra effects we do this in its own pass @@ -908,7 +914,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Post process pass } - if (render_buffer) { + if (rb_data.is_valid()) { _disable_clear_request(p_render_data); } } @@ -932,26 +938,29 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = p_instances.size(); p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_instances.size(); } + + RenderSceneDataRD scene_data; + scene_data.cam_projection = p_projection; + scene_data.cam_transform = p_transform; + scene_data.view_projection[0] = p_projection; + scene_data.z_near = 0.0; + scene_data.z_far = p_zfar; + scene_data.lod_camera_plane = p_camera_plane; + scene_data.lod_distance_multiplier = p_lod_distance_multiplier; + scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; + scene_data.opaque_prepass_threshold = 0.1; + RenderDataRD render_data; - render_data.cam_projection = p_projection; - render_data.cam_transform = p_transform; - render_data.view_projection[0] = p_projection; - render_data.z_near = 0.0; - render_data.z_far = p_zfar; + render_data.scene_data = &scene_data; render_data.instances = &p_instances; render_data.render_info = p_render_info; - render_data.lod_camera_plane = p_camera_plane; - render_data.lod_distance_multiplier = p_lod_distance_multiplier; - - scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; - scene_state.ubo.opaque_prepass_threshold = 0.1; _setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index); if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { - render_data.screen_mesh_lod_threshold = 0.0; + scene_data.screen_mesh_lod_threshold = 0.0; } else { - render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; + scene_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; } PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW; @@ -976,8 +985,8 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete shadow_pass.camera_plane = p_camera_plane; - shadow_pass.screen_mesh_lod_threshold = render_data.screen_mesh_lod_threshold; - shadow_pass.lod_distance_multiplier = render_data.lod_distance_multiplier; + shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold; + shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier; shadow_pass.framebuffer = p_framebuffer; shadow_pass.initial_depth_action = p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE : RD::INITIAL_ACTION_CONTINUE); @@ -1024,15 +1033,17 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c _update_render_base_uniform_set(); - scene_state.ubo.dual_paraboloid_side = 0; - scene_state.ubo.material_uv2_mode = false; - scene_state.ubo.opaque_prepass_threshold = 0.0f; - scene_state.ubo.emissive_exposure_normalization = p_exposure_normalization; + RenderSceneDataRD scene_data; + scene_data.cam_projection = p_cam_projection; + scene_data.cam_transform = p_cam_transform; + scene_data.view_projection[0] = p_cam_projection; + scene_data.dual_paraboloid_side = 0; + scene_data.material_uv2_mode = false; + scene_data.opaque_prepass_threshold = 0.0f; + scene_data.emissive_exposure_normalization = p_exposure_normalization; RenderDataRD render_data; - render_data.cam_projection = p_cam_projection; - render_data.cam_transform = p_cam_transform; - render_data.view_projection[0] = p_cam_projection; + render_data.scene_data = &scene_data; render_data.instances = &p_instances; _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); @@ -1071,11 +1082,13 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> _update_render_base_uniform_set(); - scene_state.ubo.dual_paraboloid_side = 0; - scene_state.ubo.material_uv2_mode = true; - scene_state.ubo.emissive_exposure_normalization = -1.0; + RenderSceneDataRD scene_data; + scene_data.dual_paraboloid_side = 0; + scene_data.material_uv2_mode = true; + scene_data.emissive_exposure_normalization = -1.0; RenderDataRD render_data; + render_data.scene_data = &scene_data; render_data.instances = &p_instances; _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); @@ -1132,7 +1145,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> RD::get_singleton()->draw_command_end_label(); } -void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) { +void RenderForwardMobile::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) { // we don't do GI in low end.. } @@ -1142,15 +1155,18 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); _update_render_base_uniform_set(); - scene_state.ubo.dual_paraboloid_side = 0; - scene_state.ubo.opaque_prepass_threshold = 0.0; + + RenderSceneDataRD scene_data; + scene_data.cam_projection = p_cam_projection; + scene_data.cam_transform = p_cam_transform; + scene_data.view_projection[0] = p_cam_projection; + scene_data.z_near = 0.0; + scene_data.z_far = p_cam_projection.get_z_far(); + scene_data.dual_paraboloid_side = 0; + scene_data.opaque_prepass_threshold = 0.0; RenderDataRD render_data; - render_data.cam_projection = p_cam_projection; - render_data.cam_transform = p_cam_transform; - render_data.view_projection[0] = p_cam_projection; - render_data.z_near = 0.0; - render_data.z_far = p_cam_projection.get_z_far(); + render_data.scene_data = &scene_data; render_data.instances = &p_instances; _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); @@ -1364,15 +1380,11 @@ void RenderForwardMobile::_update_render_base_uniform_set() { } } -RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers) { - // RenderBufferDataForwardMobile *rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffers); - - // We don't have this. This is for debugging - // return rb->normal_roughness_buffer; +RID RenderForwardMobile::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) { return RID(); } -RID RenderForwardMobile::_render_buffers_get_velocity_texture(RID p_render_buffers) { +RID RenderForwardMobile::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) { return RID(); } @@ -1393,9 +1405,9 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } uint32_t lightmap_captures_used = 0; - Plane near_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin); - near_plane.d += p_render_data->cam_projection.get_z_near(); - float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near(); + Plane near_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); + near_plane.d += p_render_data->scene_data->cam_projection.get_z_near(); + float z_max = p_render_data->scene_data->cam_projection.get_z_far() - p_render_data->scene_data->cam_projection.get_z_near(); RenderList *rl = &render_list[p_render_list]; @@ -1474,13 +1486,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const // LOD - if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) { //lod - Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal); - Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal); + Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->scene_data->lod_camera_plane.normal); + Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->scene_data->lod_camera_plane.normal); - float distance_min = p_render_data->lod_camera_plane.distance_to(lod_support_min); - float distance_max = p_render_data->lod_camera_plane.distance_to(lod_support_max); + float distance_min = p_render_data->scene_data->lod_camera_plane.distance_to(lod_support_min); + float distance_max = p_render_data->scene_data->lod_camera_plane.distance_to(lod_support_max); float distance = 0.0; @@ -1493,12 +1505,12 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const distance = -distance_max; } - if (p_render_data->cam_orthogonal) { + if (p_render_data->scene_data->cam_orthogonal) { distance = 1.0; } uint32_t indices; - surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices); + surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, &indices); if (p_render_data->render_info) { indices = _indices_to_primitives(surf->primitive, indices); if (p_render_list == RENDER_LIST_OPAQUE) { //opaque @@ -1570,215 +1582,20 @@ 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) { - //!BAS! need to go through this and find out what we don't need anymore - - // This populates our UBO with main scene data that is pushed into set 1 - - //Projection projection = p_render_data->cam_projection; - //projection.flip_y(); // Vulkan and modern APIs use Y-Down - Projection correction; - correction.set_depth_correction(p_flip_y); - Projection projection = correction * p_render_data->cam_projection; - - //store camera into ubo - RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); - RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); - RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); - - for (uint32_t v = 0; v < p_render_data->view_count; v++) { - projection = correction * p_render_data->view_projection[v]; - RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); - RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); - - scene_state.ubo.eye_offset[v][0] = p_render_data->view_eye_offset[v].x; - scene_state.ubo.eye_offset[v][1] = p_render_data->view_eye_offset[v].y; - scene_state.ubo.eye_offset[v][2] = p_render_data->view_eye_offset[v].z; - scene_state.ubo.eye_offset[v][3] = 0.0; - } - - scene_state.ubo.z_far = p_render_data->z_far; - scene_state.ubo.z_near = p_render_data->z_near; - - scene_state.ubo.pancake_shadows = p_pancake_shadows; - - RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); - RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); - RendererRD::MaterialStorage::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); - RendererRD::MaterialStorage::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); - - Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size); - scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x; - scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y; - - if (p_render_data->shadow_atlas.is_valid()) { - Vector2 sas = shadow_atlas_get_size(p_render_data->shadow_atlas); - scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x; - scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y; - } - { - Vector2 dss = directional_shadow_get_size(); - scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x; - scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y; - } - - //time global variables - scene_state.ubo.time = time; - - /* - scene_state.ubo.gi_upscale_for_msaa = false; - scene_state.ubo.volumetric_fog_enabled = false; - scene_state.ubo.fog_enabled = false; - - if (p_render_data->render_buffers.is_valid()) { - RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers)); - if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { - scene_state.ubo.gi_upscale_for_msaa = true; - } - - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers)) { - scene_state.ubo.volumetric_fog_enabled = true; - float fog_end = render_buffers_get_volumetric_fog_end(p_render_data->render_buffers); - if (fog_end > 0.0) { - scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end; - } else { - scene_state.ubo.volumetric_fog_inv_length = 1.0; - } - - float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_data->render_buffers); //reverse lookup - if (fog_detail_spread > 0.0) { - scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread; - } else { - scene_state.ubo.volumetric_fog_detail_spread = 1.0; - } - } - } - - */ - - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { - scene_state.ubo.use_ambient_light = true; - scene_state.ubo.ambient_light_color_energy[0] = 1; - scene_state.ubo.ambient_light_color_energy[1] = 1; - scene_state.ubo.ambient_light_color_energy[2] = 1; - scene_state.ubo.ambient_light_color_energy[3] = 1.0; - scene_state.ubo.use_ambient_cubemap = false; - scene_state.ubo.use_reflection_cubemap = false; - scene_state.ubo.ssao_enabled = false; - - } else if (is_environment(p_render_data->environment)) { - RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment); - RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment); - - float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment); - - scene_state.ubo.ambient_light_color_energy[3] = bg_energy_multiplier; - - scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment); - - //ambient - if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { - Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); - color = color.srgb_to_linear(); - - scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier; - scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier; - scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier; - scene_state.ubo.use_ambient_light = true; - scene_state.ubo.use_ambient_cubemap = false; - } else { - float energy = environment_get_ambient_light_energy(p_render_data->environment); - Color color = environment_get_ambient_light(p_render_data->environment); - color = color.srgb_to_linear(); - scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; - scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; - scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; - - Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); - sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; - RendererRD::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); - - scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; - scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; - } - - //specular - RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_render_data->environment); - if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) { - scene_state.ubo.use_reflection_cubemap = true; - } else { - scene_state.ubo.use_reflection_cubemap = false; - } - - scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_get_ssao_enabled(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); - - scene_state.ubo.fog_enabled = environment_get_fog_enabled(p_render_data->environment); - scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment); - scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment); - scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment); - scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment); - - Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear(); - float fog_energy = environment_get_fog_light_energy(p_render_data->environment); - - scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; - scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy; - scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy; - - scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment); - - } else { - if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { - scene_state.ubo.use_ambient_light = false; - } else { - scene_state.ubo.use_ambient_light = true; - Color clear_color = p_default_bg_color; - clear_color = clear_color.srgb_to_linear(); - scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; - scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; - scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; - scene_state.ubo.ambient_light_color_energy[3] = 1.0; - } - - scene_state.ubo.use_ambient_cubemap = false; - scene_state.ubo.use_reflection_cubemap = false; - scene_state.ubo.ssao_enabled = false; - } - - if (p_render_data->camera_attributes.is_valid()) { - scene_state.ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); - scene_state.ubo.IBL_exposure_normalization = 1.0; - if (is_environment(p_render_data->environment)) { - RID sky_rid = environment_get_sky(p_render_data->environment); - if (sky_rid.is_valid()) { - float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes) * environment_get_bg_intensity(p_render_data->environment) / _render_buffers_get_luminance_multiplier(); - scene_state.ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, sky.sky_get_baked_exposure(sky_rid)); - } - } - } else if (scene_state.ubo.emissive_exposure_normalization > 0.0) { - // This branch is triggered when using render_material(). - // Emissive is set outside the function, so don't set it. - // IBL isn't used don't set it. - } else { - scene_state.ubo.emissive_exposure_normalization = 1.0; - scene_state.ubo.IBL_exposure_normalization = 1.0; - } - - scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active(); - scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount(); - scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit(); + 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() ? reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); + // May do this earlier in RenderSceneRenderRD::render_scene if (p_index >= (int)scene_state.uniform_buffers.size()) { uint32_t from = scene_state.uniform_buffers.size(); scene_state.uniform_buffers.resize(p_index + 1); - render_pass_uniform_sets.resize(p_index + 1); for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) { - scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); + scene_state.uniform_buffers[i] = p_render_data->scene_data->create_uniform_buffer(); } } - RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER); + + p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers); } void RenderForwardMobile::_fill_element_info(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements) { diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index cc3e245f2f..b2adebbf6a 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -37,6 +37,8 @@ #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/utilities.h" +#define RB_SCOPE_MOBILE SNAME("mobile") + namespace RendererSceneRenderImplementation { class RenderForwardMobile : public RendererSceneRenderRD { @@ -107,43 +109,38 @@ protected: /* Render Buffer */ - // We can have: - // - 4 subpasses combining the full render cycle - // - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer) - // - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer) - enum RenderBufferMobileFramebufferConfigType { - FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass - FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass - FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass - FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass - FB_CONFIG_MAX - }; - - struct RenderBufferDataForwardMobile : public RenderBufferData { - RID color; - RID depth; - // RID normal_roughness_buffer; + class RenderBufferDataForwardMobile : public RenderBufferCustomDataRD { + GDCLASS(RenderBufferDataForwardMobile, RenderBufferCustomDataRD); - RS::ViewportMSAA msaa; - RD::TextureSamples texture_samples; - - RID color_msaa; - RID depth_msaa; - // RID normal_roughness_buffer_msaa; + public: + // We can have: + // - 4 subpasses combining the full render cycle + // - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer) + // - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer) + enum FramebufferConfigType { + FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass + FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass + FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass + FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass + FB_CONFIG_MAX + }; - RID vrs; + RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA); } + RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, p_layer, 0); } - RID color_fbs[FB_CONFIG_MAX]; - int width, height; - uint32_t view_count; + RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA); } + RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, p_layer, 0); } - void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); + RID get_color_fbs(FramebufferConfigType p_config_type); + virtual void free_data() override; + virtual void configure(RenderSceneBuffersRD *p_render_buffers) override; - ~RenderBufferDataForwardMobile(); + private: + RenderSceneBuffersRD *render_buffers = nullptr; + RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1; }; - virtual RenderBufferData *_create_render_buffer_data() override; + virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override; /* Rendering */ @@ -218,15 +215,15 @@ protected: virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; + virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; uint64_t lightmap_texture_array_version = 0xFFFFFFFF; virtual void _base_uniforms_changed() override; void _update_render_base_uniform_set(); - virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override; - virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override; + virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false); void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1); @@ -255,75 +252,6 @@ protected: /* Scene state */ struct SceneState { - // This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code - struct UBO { - float projection_matrix[16]; - float inv_projection_matrix[16]; - float inv_view_matrix[16]; - float view_matrix[16]; - - float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; - float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; - float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4]; - - float viewport_size[2]; - float screen_pixel_size[2]; - - float directional_penumbra_shadow_kernel[128]; //32 vec4s - float directional_soft_shadow_kernel[128]; - float penumbra_shadow_kernel[128]; - float soft_shadow_kernel[128]; - - float ambient_light_color_energy[4]; - - float ambient_color_sky_mix; - uint32_t use_ambient_light; - uint32_t use_ambient_cubemap; - uint32_t use_reflection_cubemap; - - float radiance_inverse_xform[12]; - - float shadow_atlas_pixel_size[2]; - float directional_shadow_pixel_size[2]; - - uint32_t directional_light_count; - float dual_paraboloid_side; - float z_far; - float z_near; - - uint32_t ssao_enabled; - float ssao_light_affect; - float ssao_ao_affect; - uint32_t roughness_limiter_enabled; - - float roughness_limiter_amount; - float roughness_limiter_limit; - float opaque_prepass_threshold; - uint32_t roughness_limiter_pad; - - // Fog - uint32_t fog_enabled; - float fog_density; - float fog_height; - float fog_height_density; - - float fog_light_color[3]; - float fog_sun_scatter; - - float fog_aerial_perspective; - uint32_t material_uv2_mode; - - float time; - float reflection_multiplier; - - uint32_t pancake_shadows; - float emissive_exposure_normalization; // Needed to normalize emissive when using physical units. - float IBL_exposure_normalization; // Adjusts for baked exposure. - uint32_t pad3; - }; - - UBO ubo; - LocalVector<RID> uniform_buffers; // !BAS! We need to change lightmaps, we're not going to do this with a buffer but pushing the used lightmap in 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 85c9e1db2a..383ed9247d 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 @@ -331,7 +331,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { valid = true; } -void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void SceneShaderForwardMobile::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -403,7 +403,7 @@ void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<Renderer } } -bool SceneShaderForwardMobile::ShaderData::is_param_texture(const StringName &p_param) const { +bool SceneShaderForwardMobile::ShaderData::is_parameter_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } 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 e208334547..f67665a02f 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 @@ -32,7 +32,7 @@ #define SCENE_SHADER_FORWARD_MOBILE_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl.gen.h" namespace RendererSceneRenderImplementation { @@ -141,11 +141,11 @@ public: virtual void set_code(const String &p_Code); virtual void set_path_hint(const String &p_path); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; virtual Variant get_default_parameter(const StringName &p_parameter) const; diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h index f360e0fc6b..f50d6baa30 100644 --- a/servers/rendering/renderer_rd/framebuffer_cache_rd.h +++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h @@ -200,7 +200,7 @@ public: RID get_cache(Args... args) { uint32_t h = hash_murmur3_one_32(1); //1 view h = hash_murmur3_one_32(sizeof...(Args), h); - h = _hash_args(h, args...); + h = _hash_rids(h, args...); h = hash_murmur3_one_32(0, h); // 0 passes h = hash_fmix32(h); @@ -228,7 +228,7 @@ public: RID get_cache_multiview(uint32_t p_views, Args... args) { uint32_t h = hash_murmur3_one_32(p_views); h = hash_murmur3_one_32(sizeof...(Args), h); - h = _hash_args(h, args...); + h = _hash_rids(h, args...); h = hash_murmur3_one_32(0, h); // 0 passes h = hash_fmix32(h); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 7102f1f0ff..ab3e3ebe51 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2192,7 +2192,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { valid = true; } -void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -2264,7 +2264,7 @@ void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<Rend } } -bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const { +bool RendererCanvasRenderRD::CanvasShaderData::is_parameter_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 54077a5b9a..67db56d913 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -182,11 +182,11 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual void set_code(const String &p_Code); virtual void set_path_hint(const String &p_path); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; virtual Variant get_default_parameter(const StringName &p_parameter) const; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index a95dbbe779..7841e36244 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -51,16 +51,21 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) { } } -void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); +void RendererSceneRenderRD::sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) { + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND(rb.is_null()); + Ref<RendererRD::GI::SDFGI> sdfgi; + if (rb->has_custom_data(RB_SCOPE_SDFGI)) { + sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + } + bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment); if (!needs_sdfgi) { - if (rb->sdfgi != nullptr) { - //erase it - rb->sdfgi->erase(); - memdelete(rb->sdfgi); - rb->sdfgi = nullptr; + if (sdfgi.is_valid()) { + // delete it + sdfgi.unref(); + rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); } return; } @@ -68,35 +73,34 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 }; uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge]; - if (rb->sdfgi && (rb->sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || rb->sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || rb->sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) { + if (sdfgi.is_valid() && (sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != sdfgi->history_size || sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) { //configuration changed, erase - rb->sdfgi->erase(); - memdelete(rb->sdfgi); - rb->sdfgi = nullptr; + sdfgi.unref(); + rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); } - RendererRD::GI::SDFGI *sdfgi = rb->sdfgi; - if (sdfgi == nullptr) { + if (sdfgi.is_null()) { // re-create - rb->sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size); + sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size); + rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi); } else { //check for updates - rb->sdfgi->update(p_environment, p_world_position); + sdfgi->update(p_environment, p_world_position); } } -int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers) const { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - - ERR_FAIL_COND_V(rb == nullptr, 0); +int RendererSceneRenderRD::sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const { + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND_V(rb.is_null(), 0); - if (rb->sdfgi == nullptr) { + if (!rb->has_custom_data(RB_SCOPE_SDFGI)) { return 0; } + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); int dirty_count = 0; - for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { - const RendererRD::GI::SDFGI::Cascade &c = rb->sdfgi->cascades[i]; + for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { + const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i]; if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) { dirty_count++; @@ -112,28 +116,32 @@ int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers) return dirty_count; } -AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const { +AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const { AABB bounds; Vector3i from; Vector3i size; - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(rb == nullptr, AABB()); - ERR_FAIL_COND_V(rb->sdfgi == nullptr, AABB()); - int c = rb->sdfgi->get_pending_region_data(p_region, from, size, bounds); + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND_V(rb.is_null(), AABB()); + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + ERR_FAIL_COND_V(sdfgi.is_null(), AABB()); + + int c = sdfgi->get_pending_region_data(p_region, from, size, bounds); ERR_FAIL_COND_V(c == -1, AABB()); return bounds; } -uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const { +uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const { AABB bounds; Vector3i from; Vector3i size; - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(rb == nullptr, -1); - ERR_FAIL_COND_V(rb->sdfgi == nullptr, -1); - return rb->sdfgi->get_pending_region_data(p_region, from, size, bounds); + Ref<RenderSceneBuffersRD> rb = p_render_buffers; + ERR_FAIL_COND_V(rb.is_null(), -1); + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); + ERR_FAIL_COND_V(sdfgi.is_null(), -1); + + return sdfgi->get_pending_region_data(p_region, from, size, bounds); } RID RendererSceneRenderRD::sky_allocate() { @@ -1217,191 +1225,44 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this); } -void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); +void RendererSceneRenderRD::_debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { + ERR_FAIL_COND(p_render_buffers.is_null()); - if (!rb->sdfgi) { + if (!p_render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { return; //nothing to debug } - rb->sdfgi->debug_probes(p_framebuffer, p_view_count, p_camera_with_transforms, p_will_continue_color, p_will_continue_depth); -} + Ref<RendererRD::GI::SDFGI> sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); -//////////////////////////////// -RID RendererSceneRenderRD::render_buffers_create() { - RenderBuffers rb; - rb.data = _create_render_buffer_data(); - return render_buffers_owner.make_rid(rb); + sdfgi->debug_probes(p_framebuffer, p_view_count, p_camera_with_transforms, p_will_continue_color, p_will_continue_depth); } -void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) { - ERR_FAIL_COND(!rb->blur[0].texture.is_null()); - - uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); - - RD::TextureFormat tf; - tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->internal_width; - tf.height = rb->internal_height; - tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D; - tf.array_layers = rb->view_count; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - if (_render_buffers_can_be_storage()) { - tf.usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT; - } else { - tf.usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - } - tf.mipmaps = mipmaps_required; - - rb->sss_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - tf.width = rb->internal_width; - tf.height = rb->internal_height; - rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - //the second one is smaller (only used for separatable part of blur) - tf.width >>= 1; - tf.height >>= 1; - tf.mipmaps--; - rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - for (uint32_t l = 0; l < rb->view_count; l++) { - RenderBuffers::Blur::Layer ll[2]; - int base_width = rb->internal_width; - int base_height = rb->internal_height; - - for (uint32_t i = 0; i < mipmaps_required; i++) { - RenderBuffers::Blur::Mipmap mm; - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, l, i); - - mm.width = base_width; - mm.height = base_height; - - if (!_render_buffers_can_be_storage()) { - Vector<RID> fb; - fb.push_back(mm.texture); - - mm.fb = RD::get_singleton()->framebuffer_create(fb); - } - - if (!_render_buffers_can_be_storage()) { - // and half texture, this is an intermediate result so just allocate a texture, is this good enough? - tf.width = MAX(1, base_width >> 1); - tf.height = base_height; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; - tf.mipmaps = 1; - - mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - Vector<RID> half_fb; - half_fb.push_back(mm.half_texture); - mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb); - } - - ll[0].mipmaps.push_back(mm); - - if (i > 0) { - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, l, i - 1); - - if (!_render_buffers_can_be_storage()) { - Vector<RID> fb; - fb.push_back(mm.texture); - - mm.fb = RD::get_singleton()->framebuffer_create(fb); - - // We can re-use the half texture here as it is an intermediate result - } - - ll[1].mipmaps.push_back(mm); - } - - base_width = MAX(1, base_width >> 1); - base_height = MAX(1, base_height >> 1); - } - - rb->blur[0].layers.push_back(ll[0]); - rb->blur[1].layers.push_back(ll[1]); - } - - if (!_render_buffers_can_be_storage()) { - // create 4 weight textures, 2 full size, 2 half size - - tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP - tf.width = rb->internal_width; - tf.height = rb->internal_height; - tf.texture_type = RD::TEXTURE_TYPE_2D; - tf.array_layers = 1; // Our DOF effect handles one eye per turn - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tf.mipmaps = 1; - for (uint32_t i = 0; i < 4; i++) { - // associated blur texture - RID texture; - if (i == 1) { - texture = rb->blur[0].layers[0].mipmaps[0].texture; - } else if (i == 2) { - texture = rb->blur[1].layers[0].mipmaps[0].texture; - } else if (i == 3) { - texture = rb->blur[0].layers[0].mipmaps[1].texture; - } - - // create weight texture - rb->weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - // create frame buffer - Vector<RID> fb; - if (i != 0) { - fb.push_back(texture); - } - fb.push_back(rb->weight_buffers[i].weight); - rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb); +//////////////////////////////// +Ref<RenderSceneBuffers> RendererSceneRenderRD::render_buffers_create() { + Ref<RenderSceneBuffersRD> rb; + rb.instantiate(); - if (i == 1) { - // next 2 are half size - tf.width = MAX(1u, tf.width >> 1); - tf.height = MAX(1u, tf.height >> 1); - } - } + rb->set_can_be_storage(_render_buffers_can_be_storage()); + rb->set_max_cluster_elements(max_cluster_elements); + rb->set_base_data_format(_render_buffers_get_color_format()); + if (ss_effects) { + rb->set_sseffects(ss_effects); } -} - -void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *rb) { - ERR_FAIL_COND(!rb->depth_back_texture.is_null()); - - { - RD::TextureFormat tf; - if (rb->view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - } - // We're not using this as a depth stencil, just copying our data into this. May need to look into using a different format on mobile, maybe R16? - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; - tf.array_layers = rb->view_count; // create a layer for every view - - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; // set this as color attachment because we're copying data into it, it's not actually used as a depth buffer - - rb->depth_back_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (vrs) { + rb->set_vrs(vrs); } - if (!_render_buffers_can_be_storage()) { - // create framebuffer so we can write into this... - - Vector<RID> fb; - fb.push_back(rb->depth_back_texture); + setup_render_buffer_data(rb); - rb->depth_back_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count); - } + return rb; } -void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) { +void RendererSceneRenderRD::_allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb) { ERR_FAIL_COND(!rb->luminance.current.is_null()); - int w = rb->internal_width; - int h = rb->internal_height; + Size2i internal_size = rb->get_internal_size(); + int w = internal_size.x; + int h = internal_size.y; while (true) { w = MAX(w / 8, 1); @@ -1447,211 +1308,60 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) { } } -void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { - if (rb->views.size() > 1) { // if 1 these are copies ofs rb->internal_texture, rb->depth_texture and rb->texture_fb - for (int i = 0; i < rb->views.size(); i++) { - if (rb->views[i].view_fb.is_valid()) { - RD::get_singleton()->free(rb->views[i].view_fb); - } - if (rb->views[i].view_texture.is_valid()) { - RD::get_singleton()->free(rb->views[i].view_texture); - } - if (rb->views[i].view_depth.is_valid()) { - RD::get_singleton()->free(rb->views[i].view_depth); - } - } - } - rb->views.clear(); - - if (rb->texture_fb.is_valid()) { - RD::get_singleton()->free(rb->texture_fb); - rb->texture_fb = RID(); - } - - if (rb->internal_texture == rb->texture && rb->internal_texture.is_valid()) { - RD::get_singleton()->free(rb->internal_texture); - rb->texture = RID(); - rb->internal_texture = RID(); - rb->upscale_texture = RID(); - } else { - if (rb->texture.is_valid()) { - RD::get_singleton()->free(rb->texture); - rb->texture = RID(); - } - - if (rb->internal_texture.is_valid()) { - RD::get_singleton()->free(rb->internal_texture); - rb->internal_texture = RID(); - } - - if (rb->upscale_texture.is_valid()) { - RD::get_singleton()->free(rb->upscale_texture); - rb->upscale_texture = RID(); - } - } - - if (rb->depth_texture.is_valid()) { - RD::get_singleton()->free(rb->depth_texture); - rb->depth_texture = RID(); - } - - if (rb->depth_back_fb.is_valid()) { - RD::get_singleton()->free(rb->depth_back_fb); - rb->depth_back_fb = RID(); - } - - if (rb->depth_back_texture.is_valid()) { - RD::get_singleton()->free(rb->depth_back_texture); - rb->depth_back_texture = RID(); - } - - if (rb->sss_texture.is_valid()) { - RD::get_singleton()->free(rb->sss_texture); - rb->sss_texture = RID(); - } - - if (rb->vrs_fb.is_valid()) { - RD::get_singleton()->free(rb->vrs_fb); - rb->vrs_fb = RID(); - } - - if (rb->vrs_texture.is_valid()) { - RD::get_singleton()->free(rb->vrs_texture); - rb->vrs_texture = RID(); - } - - for (int i = 0; i < 2; i++) { - for (int l = 0; l < rb->blur[i].layers.size(); l++) { - for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) { - // do we free the texture slice here? or is it enough to free the main texture? - - // do free the mobile extra stuff - if (rb->blur[i].layers[l].mipmaps[m].fb.is_valid()) { - RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].fb); - } - // texture and framebuffer in both blur mipmaps are shared, so only free from the first one - if (i == 0) { - if (rb->blur[i].layers[l].mipmaps[m].half_fb.is_valid()) { - RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_fb); - } - if (rb->blur[i].layers[l].mipmaps[m].half_texture.is_valid()) { - RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_texture); - } - } - } - } - rb->blur[i].layers.clear(); - - if (rb->blur[i].texture.is_valid()) { - RD::get_singleton()->free(rb->blur[i].texture); - rb->blur[i].texture = RID(); - } - } - - for (int i = 0; i < rb->luminance.fb.size(); i++) { - RD::get_singleton()->free(rb->luminance.fb[i]); - } - rb->luminance.fb.clear(); - - for (int i = 0; i < rb->luminance.reduce.size(); i++) { - RD::get_singleton()->free(rb->luminance.reduce[i]); - } - rb->luminance.reduce.clear(); - - if (rb->luminance.current_fb.is_valid()) { - RD::get_singleton()->free(rb->luminance.current_fb); - rb->luminance.current_fb = RID(); - } - - if (rb->luminance.current.is_valid()) { - RD::get_singleton()->free(rb->luminance.current); - rb->luminance.current = RID(); - } - - if (rb->ss_effects.linear_depth.is_valid()) { - RD::get_singleton()->free(rb->ss_effects.linear_depth); - rb->ss_effects.linear_depth = RID(); - rb->ss_effects.linear_depth_slices.clear(); - } - - ss_effects->ssao_free(rb->ss_effects.ssao); - ss_effects->ssil_free(rb->ss_effects.ssil); - ss_effects->ssr_free(rb->ssr); - - if (rb->taa.history.is_valid()) { - RD::get_singleton()->free(rb->taa.history); - rb->taa.history = RID(); - } - - if (rb->taa.temp.is_valid()) { - RD::get_singleton()->free(rb->taa.temp); - rb->taa.temp = RID(); - } - - if (rb->taa.prev_velocity.is_valid()) { - RD::get_singleton()->free(rb->taa.prev_velocity); - rb->taa.prev_velocity = RID(); - } - - rb->rbgi.free(); -} - -void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const Projection &p_camera) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); +void RendererSceneRenderRD::_process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera) { + ERR_FAIL_COND(p_render_buffers.is_null()); - bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8; + Size2i internal_size = p_render_buffers->get_internal_size(); + bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8; if (!can_use_effects) { //just copy return; } - if (rb->blur[0].texture.is_null()) { - _allocate_blur_textures(rb); - } + p_render_buffers->allocate_blur_textures(); - RendererCompositorRD::singleton->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality); + for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) { + RID internal_texture = p_render_buffers->get_internal_texture(v); + RID depth_texture = p_render_buffers->get_depth_texture(v); + ss_effects->sub_surface_scattering(p_render_buffers, internal_texture, depth_texture, p_camera, internal_size, sss_scale, sss_depth_scale, sss_quality); + } } -void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) { +void RendererSceneRenderRD::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) { ERR_FAIL_NULL(ss_effects); + ERR_FAIL_COND(p_render_buffers.is_null()); - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); - - bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8; + Size2i internal_size = p_render_buffers->get_internal_size(); + bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8; + uint32_t view_count = p_render_buffers->get_view_count(); if (!can_use_effects) { //just copy - copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID(), rb->view_count); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), RID(), view_count); return; } ERR_FAIL_COND(p_environment.is_null()); - ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment)); - Size2i half_size = Size2i(rb->internal_width / 2, rb->internal_height / 2); - if (rb->ssr.output.is_null()) { - ss_effects->ssr_allocate_buffers(rb->ssr, _render_buffers_get_color_format(), ssr_roughness_quality, half_size, rb->view_count); + Size2i half_size = Size2i(internal_size.x / 2, internal_size.y / 2); + if (p_render_buffers->ssr.output.is_null()) { + ss_effects->ssr_allocate_buffers(p_render_buffers->ssr, _render_buffers_get_color_format(), ssr_roughness_quality, half_size, view_count); } RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS]; RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS]; - for (uint32_t v = 0; v < rb->view_count; v++) { - texture_slices[v] = rb->views[v].view_texture; - depth_slices[v] = rb->views[v].view_depth; + for (uint32_t v = 0; v < view_count; v++) { + texture_slices[v] = p_render_buffers->get_internal_texture(v); + depth_slices[v] = p_render_buffers->get_depth_texture(v); } - ss_effects->screen_space_reflection(rb->ssr, texture_slices, p_normal_slices, ssr_roughness_quality, p_metallic_slices, p_metallic_mask, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), rb->view_count, p_projections, p_eye_offsets); - copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->ssr.output, rb->view_count); + ss_effects->screen_space_reflection(p_render_buffers->ssr, texture_slices, p_normal_slices, ssr_roughness_quality, p_metallic_slices, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), view_count, p_projections, p_eye_offsets); + copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), p_render_buffers->ssr.output, view_count); } -void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) { +void RendererSceneRenderRD::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) { ERR_FAIL_NULL(ss_effects); - - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); - + ERR_FAIL_COND(p_render_buffers.is_null()); ERR_FAIL_COND(p_environment.is_null()); RENDER_TIMESTAMP("Process SSAO"); @@ -1670,18 +1380,15 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen settings.blur_passes = ssao_blur_passes; settings.fadeout_from = ssao_fadeout_from; settings.fadeout_to = ssao_fadeout_to; - settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height); + settings.full_screen_size = p_render_buffers->get_internal_size(); - ss_effects->ssao_allocate_buffers(rb->ss_effects.ssao, settings, rb->ss_effects.linear_depth); - ss_effects->generate_ssao(rb->ss_effects.ssao, p_normal_buffer, p_projection, settings); + ss_effects->ssao_allocate_buffers(p_render_buffers->ss_effects.ssao, settings, p_render_buffers->ss_effects.linear_depth); + ss_effects->generate_ssao(p_render_buffers->ss_effects.ssao, p_normal_buffer, p_projection, settings); } -void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) { +void RendererSceneRenderRD::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) { ERR_FAIL_NULL(ss_effects); - - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); - + ERR_FAIL_COND(p_render_buffers.is_null()); ERR_FAIL_COND(p_environment.is_null()); RENDER_TIMESTAMP("Process SSIL"); @@ -1698,95 +1405,71 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen settings.blur_passes = ssil_blur_passes; settings.fadeout_from = ssil_fadeout_from; settings.fadeout_to = ssil_fadeout_to; - settings.full_screen_size = Size2i(rb->width, rb->height); + settings.full_screen_size = p_render_buffers->get_internal_size(); Projection correction; correction.set_depth_correction(true); Projection projection = correction * p_projection; Transform3D transform = p_transform; transform.set_origin(Vector3(0.0, 0.0, 0.0)); - Projection last_frame_projection = rb->ss_effects.last_frame_projection * Projection(rb->ss_effects.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); + Projection last_frame_projection = p_render_buffers->ss_effects.last_frame_projection * Projection(p_render_buffers->ss_effects.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse(); - ss_effects->ssil_allocate_buffers(rb->ss_effects.ssil, settings, rb->ss_effects.linear_depth); - ss_effects->screen_space_indirect_lighting(rb->ss_effects.ssil, p_normal_buffer, p_projection, last_frame_projection, settings); - rb->ss_effects.last_frame_projection = projection; - rb->ss_effects.last_frame_transform = transform; + ss_effects->ssil_allocate_buffers(p_render_buffers->ss_effects.ssil, settings, p_render_buffers->ss_effects.linear_depth); + ss_effects->screen_space_indirect_lighting(p_render_buffers->ss_effects.ssil, p_normal_buffer, p_projection, last_frame_projection, settings); + p_render_buffers->ss_effects.last_frame_projection = projection; + p_render_buffers->ss_effects.last_frame_transform = transform; } -void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); +void RendererSceneRenderRD::_copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers) { + ERR_FAIL_COND(p_render_buffers.is_null()); - if (rb->ss_effects.ssil.last_frame.is_valid()) { - copy_effects->copy_to_rect(rb->texture, rb->ss_effects.ssil.last_frame, Rect2i(0, 0, rb->width, rb->height)); + if (p_render_buffers->ss_effects.ssil.last_frame.is_valid()) { + Size2i size = p_render_buffers->get_internal_size(); + RID texture = p_render_buffers->get_internal_texture(); + copy_effects->copy_to_rect(texture, p_render_buffers->ss_effects.ssil.last_frame, Rect2i(0, 0, size.x, size.y)); - int width = rb->width; - int height = rb->height; - for (int i = 0; i < rb->ss_effects.ssil.last_frame_slices.size() - 1; i++) { + int width = size.x; + int height = size.y; + for (int i = 0; i < p_render_buffers->ss_effects.ssil.last_frame_slices.size() - 1; i++) { width = MAX(1, width >> 1); height = MAX(1, height >> 1); - copy_effects->make_mipmap(rb->ss_effects.ssil.last_frame_slices[i], rb->ss_effects.ssil.last_frame_slices[i + 1], Size2i(width, height)); + copy_effects->make_mipmap(p_render_buffers->ss_effects.ssil.last_frame_slices[i], p_render_buffers->ss_effects.ssil.last_frame_slices[i + 1], Size2i(width, height)); } } } -void RendererSceneRenderRD::_process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); - - bool just_allocated = false; - if (rb->taa.history.is_null()) { - RD::TextureFormat tf; - if (rb->view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - } - tf.format = _render_buffers_get_color_format(); - tf.width = rb->internal_width; - tf.height = rb->internal_height; - tf.array_layers = rb->view_count; // create a layer for every view - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0); - - rb->taa.history = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->taa.temp = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - tf.format = RD::DATA_FORMAT_R16G16_SFLOAT; - rb->taa.prev_velocity = RD::get_singleton()->texture_create(tf, RD::TextureView()); - just_allocated = true; - } - - RD::get_singleton()->draw_command_begin_label("TAA"); - if (!just_allocated) { - RendererCompositorRD::singleton->get_effects()->taa_resolve(rb->internal_texture, rb->taa.temp, rb->depth_texture, p_velocity_buffer, rb->taa.prev_velocity, rb->taa.history, Size2(rb->internal_width, rb->internal_height), p_z_near, p_z_far); - copy_effects->copy_to_rect(rb->taa.temp, rb->internal_texture, Rect2(0, 0, rb->internal_width, rb->internal_height)); - } - - copy_effects->copy_to_rect(rb->internal_texture, rb->taa.history, Rect2(0, 0, rb->internal_width, rb->internal_height)); - copy_effects->copy_to_rect(p_velocity_buffer, rb->taa.prev_velocity, Rect2(0, 0, rb->width, rb->height)); - RD::get_singleton()->draw_command_end_label(); -} - void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(!rb); + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); RD::get_singleton()->draw_command_begin_label("Copy screen texture"); - if (rb->blur[0].texture.is_null()) { - _allocate_blur_textures(rb); - } + rb->allocate_blur_textures(); bool can_use_storage = _render_buffers_can_be_storage(); + Size2i size = rb->get_internal_size(); + + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + RID texture = rb->get_internal_texture(v); + int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0).mipmaps); + RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, 0); - for (uint32_t v = 0; v < rb->view_count; v++) { if (can_use_storage) { - copy_effects->copy_to_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height)); - for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) { - copy_effects->make_mipmap(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].texture, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height)); - } + copy_effects->copy_to_rect(texture, dest, Rect2i(0, 0, size.x, size.y)); } else { - copy_effects->copy_to_fb_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height)); - for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) { - copy_effects->make_mipmap_raster(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].fb, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height)); + RID fb = FramebufferCacheRD::get_singleton()->get_cache(dest); + copy_effects->copy_to_fb_rect(texture, fb, Rect2i(0, 0, size.x, size.y)); + } + + for (int i = 1; i < mipmaps; i++) { + RID source = dest; + dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i); + Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i); + + if (can_use_storage) { + copy_effects->make_mipmap(source, dest, msize); + } else { + copy_effects->make_mipmap_raster(source, dest, msize); } } } @@ -1795,23 +1478,30 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData } void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(!rb); + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); RD::get_singleton()->draw_command_begin_label("Copy depth texture"); - if (rb->depth_back_texture.is_null()) { - _allocate_depth_backbuffer_textures(rb); - } + // note, this only creates our back depth texture if we haven't already created it. + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; // set this as color attachment because we're copying data into it, it's not actually used as a depth buffer - // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye + rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, RD::DATA_FORMAT_R32_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1); bool can_use_storage = _render_buffers_can_be_storage(); + Size2i size = rb->get_internal_size(); + for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) { + RID depth_texture = rb->get_depth_texture(v); + RID depth_back_texture = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, v, 0); - if (can_use_storage) { - copy_effects->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height)); - } else { - copy_effects->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height)); + if (can_use_storage) { + copy_effects->copy_to_rect(depth_texture, depth_back_texture, Rect2i(0, 0, size.x, size.y)); + } else { + RID depth_back_fb = FramebufferCacheRD::get_singleton()->get_cache(depth_back_texture); + copy_effects->copy_to_fb_rect(depth_texture, depth_back_fb, Rect2i(0, 0, size.x, size.y)); + } } RD::get_singleton()->draw_command_end_label(); @@ -1819,37 +1509,44 @@ 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(); - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(!rb); + + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); // Glow, auto exposure and DoF (if enabled). - bool can_use_effects = rb->width >= 8 && rb->height >= 8; + + Size2i internal_size = rb->get_internal_size(); + Size2i target_size = rb->get_target_size(); + + bool can_use_effects = target_size.x >= 8 && target_size.y >= 8; // FIXME I think this should check internal size, we do all our post processing at this size... bool can_use_storage = _render_buffers_can_be_storage(); + RID render_target = rb->get_render_target(); + RID internal_texture = rb->get_internal_texture(); + if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) { RENDER_TIMESTAMP("Depth of Field"); RD::get_singleton()->draw_command_begin_label("DOF"); - if (rb->blur[0].texture.is_null()) { - _allocate_blur_textures(rb); - } + + rb->allocate_blur_textures(); RendererRD::BokehDOF::BokehBuffers buffers; // Textures we use - buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height); - buffers.secondary_texture = rb->blur[0].layers[0].mipmaps[0].texture; - buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture; - buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture; + buffers.base_texture_size = rb->get_internal_size(); + buffers.secondary_texture = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0); + buffers.half_texture[0] = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0); + buffers.half_texture[1] = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1); if (can_use_storage) { - for (uint32_t i = 0; i < rb->view_count; i++) { - buffers.base_texture = rb->views[i].view_texture; - buffers.depth_texture = rb->views[i].view_depth; + for (uint32_t i = 0; i < rb->get_view_count(); i++) { + buffers.base_texture = rb->get_internal_texture(i); + buffers.depth_texture = rb->get_depth_texture(i); // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum - float z_near = p_render_data->view_projection[i].get_z_near(); - float z_far = p_render_data->view_projection[i].get_z_far(); - bokeh_dof->bokeh_dof_compute(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->cam_orthogonal); + float z_near = p_render_data->scene_data->view_projection[i].get_z_near(); + float z_far = p_render_data->scene_data->view_projection[i].get_z_far(); + bokeh_dof->bokeh_dof_compute(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->scene_data->cam_orthogonal); }; } else { // Set framebuffers. @@ -1864,15 +1561,15 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende // Set weight buffers. buffers.base_weight_fb = rb->weight_buffers[0].fb; - for (uint32_t i = 0; i < rb->view_count; i++) { - buffers.base_texture = rb->views[i].view_texture; - buffers.depth_texture = rb->views[i].view_depth; - buffers.base_fb = rb->views[i].view_fb; + for (uint32_t i = 0; i < rb->get_view_count(); i++) { + buffers.base_texture = rb->get_internal_texture(i); + buffers.depth_texture = rb->get_depth_texture(i); + buffers.base_fb = FramebufferCacheRD::get_singleton()->get_cache(buffers.base_texture); // TODO move this into bokeh_dof_raster, we can do this internally // In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum - float z_near = p_render_data->view_projection[i].get_z_near(); - float z_far = p_render_data->view_projection[i].get_z_far(); - bokeh_dof->bokeh_dof_raster(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->cam_orthogonal); + float z_near = p_render_data->scene_data->view_projection[i].get_z_near(); + float z_far = p_render_data->scene_data->view_projection[i].get_z_far(); + bokeh_dof->bokeh_dof_raster(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->scene_data->cam_orthogonal); } } RD::get_singleton()->draw_command_end_label(); @@ -1888,16 +1585,16 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende _allocate_luminance_textures(rb); } uint64_t auto_exposure_version = RSG::camera_attributes->camera_attributes_get_auto_exposure_version(p_render_data->camera_attributes); - bool set_immediate = auto_exposure_version != rb->auto_exposure_version; - rb->auto_exposure_version = auto_exposure_version; + bool set_immediate = auto_exposure_version != rb->get_auto_exposure_version(); + rb->set_auto_exposure_version(auto_exposure_version); double step = RSG::camera_attributes->camera_attributes_get_auto_exposure_adjust_speed(p_render_data->camera_attributes) * time_step; float auto_exposure_min_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_min_sensitivity(p_render_data->camera_attributes); float auto_exposure_max_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_max_sensitivity(p_render_data->camera_attributes); if (can_use_storage) { - RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); + RendererCompositorRD::singleton->get_effects()->luminance_reduction(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); } else { - RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); + RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate); } // Swap final reduce with prev luminance. SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); @@ -1917,16 +1614,13 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende RENDER_TIMESTAMP("Glow"); RD::get_singleton()->draw_command_begin_label("Gaussian Glow"); - /* see that blur textures are allocated */ - - if (rb->blur[1].texture.is_null()) { - _allocate_blur_textures(rb); - } + rb->allocate_blur_textures(); for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { if (environment_get_glow_levels(p_render_data->environment)[i] > 0.0) { - if (i >= rb->blur[1].layers[0].mipmaps.size()) { - max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1; + int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1).mipmaps); + if (i >= mipmaps) { + max_glow_level = mipmaps - 1; } else { max_glow_level = i; } @@ -1934,26 +1628,32 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } float luminance_multiplier = _render_buffers_get_luminance_multiplier(); - for (uint32_t l = 0; l < rb->view_count; l++) { + for (uint32_t l = 0; l < rb->get_view_count(); l++) { for (int i = 0; i < (max_glow_level + 1); i++) { - int vp_w = rb->blur[1].layers[l].mipmaps[i].width; - int vp_h = rb->blur[1].layers[l].mipmaps[i].height; + Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); if (i == 0) { RID luminance_texture; if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) { luminance_texture = rb->luminance.current; } + RID source = rb->get_internal_texture(l); + RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); if (can_use_storage) { - copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); + copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); } else { - copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); + RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view + copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale); } } else { + RID source = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i - 1); + RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i); + if (can_use_storage) { - copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality); + copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality); } else { - copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), environment_get_glow_strength(p_render_data->environment), glow_high_quality); + RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view + copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality); } } } @@ -1983,10 +1683,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i]; } - tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width; - tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height; + + Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0); + tonemap.glow_texture_size.x = msize.width; + tonemap.glow_texture_size.y = msize.height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; - tonemap.glow_texture = rb->blur[1].texture; + tonemap.glow_texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1); if (environment_get_glow_map(p_render_data->environment).is_valid()) { tonemap.glow_map_strength = environment_get_glow_map_strength(p_render_data->environment); tonemap.glow_map = texture_storage->texture_get_rd_texture(environment_get_glow_map(p_render_data->environment)); @@ -2000,12 +1702,12 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE); } - if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { + if (rb->get_screen_space_aa() == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { tonemap.use_fxaa = true; } - tonemap.use_debanding = rb->use_debanding; - tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height); + tonemap.use_debanding = rb->get_use_debanding(); + tonemap.texture_size = Vector2i(rb->get_internal_size().x, rb->get_internal_size().y); if (p_render_data->environment.is_valid()) { tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment); @@ -2030,32 +1732,56 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier(); - tonemap.view_count = p_render_data->view_count; + 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 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); + dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture); + } else { + // If we do a bilinear upscale we just render into our render target and our shader will upscale automatically. + // Target size in this case is lying as we never get our real target size communicated. + // Bit nasty but... + dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target); + } - tone_mapper->tonemapper(rb->internal_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); + tone_mapper->tonemapper(internal_texture, dest_fb, tonemap); RD::get_singleton()->draw_command_end_label(); } - if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) { + 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. + RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale"); - RendererCompositorRD::singleton->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness); + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + RID source_texture = rb->get_texture_slice(SNAME("Tonemapper"), SNAME("destination"), v, 0); + RID dest_texture = texture_storage->render_target_get_rd_texture_slice(render_target, v); + + fsr->fsr_upscale(rb, source_texture, dest_texture); + } RD::get_singleton()->draw_command_end_label(); } - texture_storage->render_target_disable_clear_request(rb->render_target); + texture_storage->render_target_disable_clear_request(render_target); } void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RD::get_singleton()->draw_command_begin_label("Post Process Subpass"); - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(!rb); + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); - bool can_use_effects = rb->width >= 8 && rb->height >= 8; + // FIXME: Our input it our internal_texture, shouldn't this be using internal_size ?? + // Seeing we don't support FSR in our mobile renderer right now target_size = internal_size... + Size2i target_size = rb->get_target_size(); + bool can_use_effects = target_size.x >= 8 && target_size.y >= 8; RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass(); @@ -2100,11 +1826,11 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr } } - tonemap.use_debanding = rb->use_debanding; - tonemap.texture_size = Vector2i(rb->width, rb->height); + tonemap.use_debanding = rb->get_use_debanding(); + tonemap.texture_size = Vector2i(target_size.x, target_size.y); tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier(); - tonemap.view_count = p_render_data->view_count; + tonemap.view_count = rb->get_view_count(); tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap); @@ -2112,18 +1838,18 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr } void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_data) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(!rb); + ERR_FAIL_COND(p_render_data->render_buffers.is_null()); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - texture_storage->render_target_disable_clear_request(rb->render_target); + texture_storage->render_target_disable_clear_request(p_render_data->render_buffers->get_render_target()); } -void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) { +void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); + ERR_FAIL_COND(p_render_buffers.is_null()); + + RID render_target = p_render_buffers->get_render_target(); if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { if (p_shadow_atlas.is_valid()) { @@ -2133,17 +1859,17 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK); } - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); + Size2 rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) { if (directional_shadow_get_texture().is_valid()) { RID shadow_atlas_texture = directional_shadow_get_texture(); - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); + Size2 rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true); + copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, true); } } @@ -2151,247 +1877,59 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture(); if (decal_atlas.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); + Size2 rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true); + copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, false, true); } } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) { - if (rb->luminance.current.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); + if (p_render_buffers->luminance.current.is_valid()) { + Size2 rtsize = texture_storage->render_target_get_size(render_target); - copy_effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); + copy_effects->copy_to_fb_rect(p_render_buffers->luminance.current, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true); } } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - copy_effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && p_render_buffers->ss_effects.ssao.ao_final.is_valid()) { + Size2 rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(p_render_buffers->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true); } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - copy_effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && p_render_buffers->ss_effects.ssil.ssil_final.is_valid()) { + Size2 rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(p_render_buffers->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + Size2 rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->rbgi.ambient_buffer.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - RID ambient_texture = rb->rbgi.ambient_buffer; - RID reflection_texture = rb->rbgi.reflection_buffer; - copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture, rb->view_count > 1); + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) { + Size2 rtsize = texture_storage->render_target_get_size(render_target); + RID ambient_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_AMBIENT); + RID reflection_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_REFLECTION); + copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture, p_render_buffers->get_view_count() > 1); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { if (p_occlusion_buffer.is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); + Size2 rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize), true, false); } } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(p_render_buffers).is_valid()) { - Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); - } -} - -RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - if (!rb->blur[0].texture.is_valid()) { - return RID(); //not valid at the moment + Size2 rtsize = texture_storage->render_target_get_size(render_target); + copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false); } - return rb->blur[0].texture; -} - -RID RendererSceneRenderRD::render_buffers_get_back_depth_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - if (!rb->depth_back_texture.is_valid()) { - return RID(); //not valid at the moment - } - return rb->depth_back_texture; -} - -RID RendererSceneRenderRD::render_buffers_get_depth_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - - return rb->depth_texture; -} - -RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - - return rb->ss_effects.ssao.ao_final; -} -RID RendererSceneRenderRD::render_buffers_get_ssil_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - - return rb->ss_effects.ssil.ssil_final; -} - -RID RendererSceneRenderRD::render_buffers_get_voxel_gi_buffer(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - if (rb->rbgi.voxel_gi_buffer.is_null()) { - rb->rbgi.voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererRD::GI::VoxelGIData) * RendererRD::GI::MAX_VOXEL_GI_INSTANCES); - } - return rb->rbgi.voxel_gi_buffer; } RID RendererSceneRenderRD::render_buffers_get_default_voxel_gi_buffer() { return gi.default_voxel_gi_buffer; } -RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - - return rb->rbgi.ambient_buffer; -} -RID RendererSceneRenderRD::render_buffers_get_gi_reflection_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - return rb->rbgi.reflection_buffer; -} - -uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, 0); - ERR_FAIL_COND_V(!rb->sdfgi, 0); - - return rb->sdfgi->cascades.size(); -} -bool RendererSceneRenderRD::render_buffers_is_sdfgi_enabled(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, false); - - return rb->sdfgi != nullptr; -} -RID RendererSceneRenderRD::render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - ERR_FAIL_COND_V(!rb->sdfgi, RID()); - - return rb->sdfgi->lightprobe_texture; -} - -Vector3 RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, Vector3()); - ERR_FAIL_COND_V(!rb->sdfgi, Vector3()); - ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3()); - - return Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[p_cascade].position)) * rb->sdfgi->cascades[p_cascade].cell_size; -} - -Vector3i RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, Vector3i()); - ERR_FAIL_COND_V(!rb->sdfgi, Vector3i()); - ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3i()); - int32_t probe_divisor = rb->sdfgi->cascade_size / RendererRD::GI::SDFGI::PROBE_DIVISOR; - - return rb->sdfgi->cascades[p_cascade].position / probe_divisor; -} - -float RendererSceneRenderRD::render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, 0); - ERR_FAIL_COND_V(!rb->sdfgi, 0); - - return rb->sdfgi->normal_bias; -} -float RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, 0); - ERR_FAIL_COND_V(!rb->sdfgi, 0); - ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), 0); - - return float(rb->sdfgi->cascade_size) * rb->sdfgi->cascades[p_cascade].cell_size / float(rb->sdfgi->probe_axis_count - 1); -} -uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, 0); - ERR_FAIL_COND_V(!rb->sdfgi, 0); - - return rb->sdfgi->probe_axis_count; -} - -uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, 0); - ERR_FAIL_COND_V(!rb->sdfgi, 0); - - return rb->sdfgi->cascade_size; -} - -bool RendererSceneRenderRD::render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, false); - ERR_FAIL_COND_V(!rb->sdfgi, false); - - return rb->sdfgi->uses_occlusion; -} - -float RendererSceneRenderRD::render_buffers_get_sdfgi_energy(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, 0.0); - ERR_FAIL_COND_V(!rb->sdfgi, 0.0); - - return rb->sdfgi->energy; -} -RID RendererSceneRenderRD::render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - ERR_FAIL_COND_V(!rb->sdfgi, RID()); - - return rb->sdfgi->occlusion_texture; -} - -bool RendererSceneRenderRD::render_buffers_has_volumetric_fog(RID p_render_buffers) const { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, false); - - return rb->volumetric_fog != nullptr; -} -RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_texture(RID p_render_buffers) { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, RID()); - - return rb->volumetric_fog->fog_map; -} - -RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers) { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - - if (!rb->volumetric_fog) { - return RID(); - } - - return rb->volumetric_fog->sky_uniform_set; -} - -float RendererSceneRenderRD::render_buffers_get_volumetric_fog_end(RID p_render_buffers) { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0); - return rb->volumetric_fog->length; -} -float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers) { - const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0); - return rb->volumetric_fog->spread; -} - float RendererSceneRenderRD::_render_buffers_get_luminance_multiplier() { return 1.0; } @@ -2404,157 +1942,6 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() { return true; } -void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, 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) { - RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - - ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view"); - - if (!_render_buffers_can_be_storage()) { - p_internal_height = p_height; - p_internal_width = p_width; - } - - if (p_use_taa) { - // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. - // This restores sharpness in still images to be roughly at the same level as without TAA, - // but moving scenes will still be blurrier. - p_texture_mipmap_bias -= 0.5; - } - - if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { - // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness. - // If both TAA and FXAA are enabled, combine their negative LOD biases together. - p_texture_mipmap_bias -= 0.25; - } - - material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias); - update_uniform_sets(); - - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - - // Should we add an overrule per viewport? - rb->internal_width = p_internal_width; - rb->internal_height = p_internal_height; - rb->width = p_width; - rb->height = p_height; - rb->fsr_sharpness = p_fsr_sharpness; - rb->render_target = p_render_target; - rb->msaa_3d = p_msaa; - rb->screen_space_aa = p_screen_space_aa; - rb->use_taa = p_use_taa; - rb->use_debanding = p_use_debanding; - rb->view_count = p_view_count; - - if (is_clustered_enabled()) { - if (rb->cluster_builder == nullptr) { - rb->cluster_builder = memnew(ClusterBuilderRD); - } - rb->cluster_builder->set_shared(&cluster_builder_shared); - } - - _free_render_buffer_data(rb); - - { - RD::TextureFormat tf; - if (rb->view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - } - tf.format = _render_buffers_get_color_format(); - tf.width = rb->internal_width; // If set to rb->width, msaa won't crash - tf.height = rb->internal_height; // If set to rb->width, msaa won't crash - tf.array_layers = rb->view_count; // create a layer for every view - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - if (rb->msaa_3d != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - } - tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer - - rb->internal_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - if ((p_internal_width != p_width || p_internal_height != p_height)) { - tf.width = rb->width; - tf.height = rb->height; - rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->upscale_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } else { - rb->texture = rb->internal_texture; - rb->upscale_texture = rb->internal_texture; - } - } - - { - RD::TextureFormat tf; - if (rb->view_count > 1) { - tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - } - if (rb->msaa_3d == RS::VIEWPORT_MSAA_DISABLED) { - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; - } else { - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - } - - tf.width = rb->internal_width; - tf.height = rb->internal_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; - tf.array_layers = rb->view_count; // create a layer for every view - - if (rb->msaa_3d != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - } else { - tf.usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - } - - rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - { - if (!_render_buffers_can_be_storage()) { - // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS! - Vector<RID> fb; - fb.push_back(rb->internal_texture); - - rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count); - } - - rb->views.clear(); // JIC - if (rb->view_count == 1) { - // copy as a convenience - RenderBuffers::View view; - view.view_texture = rb->texture; - view.view_depth = rb->depth_texture; - view.view_fb = rb->texture_fb; - rb->views.push_back(view); - } else { - for (uint32_t i = 0; i < rb->view_count; i++) { - RenderBuffers::View view; - view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->texture, i, 0); - view.view_depth = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->depth_texture, i, 0); - - if (!_render_buffers_can_be_storage()) { - Vector<RID> fb; - fb.push_back(view.view_texture); - view.view_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, 1); - } - - rb->views.push_back(view); - } - } - } - - RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->render_target); - if (is_vrs_supported() && vrs_mode != RS::VIEWPORT_VRS_DISABLED) { - vrs->create_vrs_texture(p_internal_width, p_internal_height, p_view_count, rb->vrs_texture, rb->vrs_fb); - } - - RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target); - rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count, rb->vrs_texture); - - if (is_clustered_enabled()) { - rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture); - } -} - void RendererSceneRenderRD::gi_set_use_half_resolution(bool p_enable) { gi.half_resolution = p_enable; } @@ -2689,12 +2076,6 @@ bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const { return sky.sky_use_cubemap_array; } -RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_get_data(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND_V(!rb, nullptr); - return rb->data; -} - void RendererSceneRenderRD::_setup_reflections(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); cluster.reflection_count = 0; @@ -3407,20 +2788,29 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const //////////////////////////////////////////////////////////////////////////////// // FOG SHADER -void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { +void RendererSceneRenderRD::_update_volumetric_fog(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); + ERR_FAIL_COND(p_render_buffers.is_null()); + + // These should be available for our clustered renderer, at some point _update_volumetric_fog should be called by the renderer implemetentation itself + ERR_FAIL_COND(!p_render_buffers->has_custom_data(RB_SCOPE_GI)); + Ref<RendererRD::GI::RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI); - float ratio = float(rb->width) / float((rb->width + rb->height) / 2); + Ref<RendererRD::GI::SDFGI> sdfgi; + if (p_render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { + sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI); + } + + Size2i size = p_render_buffers->get_internal_size(); + float ratio = float(size.x) / float((size.x + size.y) / 2); uint32_t target_width = uint32_t(float(volumetric_fog_size) * ratio); uint32_t target_height = uint32_t(float(volumetric_fog_size) / ratio); - if (rb->volumetric_fog) { + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); //validate - if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment) || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) { - memdelete(rb->volumetric_fog); - rb->volumetric_fog = nullptr; + if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment) || fog->width != target_width || fog->height != target_height || fog->depth != volumetric_fog_depth) { + p_render_buffers->set_custom_data(RB_SCOPE_FOG, Ref<RenderBufferCustomDataRD>()); } } @@ -3429,14 +2819,21 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e return; } - if (p_environment.is_valid() && environment_get_volumetric_fog_enabled(p_environment) && !rb->volumetric_fog) { + if (p_environment.is_valid() && environment_get_volumetric_fog_enabled(p_environment) && !p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { //required volumetric fog but not existing, create - rb->volumetric_fog = memnew(RendererRD::Fog::VolumetricFog(Vector3i(target_width, target_height, volumetric_fog_depth), sky.sky_shader.default_shader_rd)); + Ref<RendererRD::Fog::VolumetricFog> fog; + + fog.instantiate(); + fog->init(Vector3i(target_width, target_height, volumetric_fog_depth), sky.sky_shader.default_shader_rd); + + p_render_buffers->set_custom_data(RB_SCOPE_FOG, fog); } - if (rb->volumetric_fog) { + if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) { + Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG); + RendererRD::Fog::VolumetricFogSettings settings; - settings.rb_size = Vector2i(rb->width, rb->height); + settings.rb_size = size; settings.time = time; settings.is_using_radiance_cubemap_array = is_using_radiance_cubemap_array(); settings.max_cluster_elements = max_cluster_elements; @@ -3445,16 +2842,16 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e settings.shadow_sampler = shadow_sampler; ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas); settings.shadow_atlas_depth = shadow_atlas ? shadow_atlas->depth : RID(); - settings.voxel_gl_buffer = render_buffers_get_voxel_gi_buffer(p_render_buffers); + settings.voxel_gi_buffer = rbgi->get_voxel_gi_buffer(); settings.omni_light_buffer = get_omni_light_buffer(); settings.spot_light_buffer = get_spot_light_buffer(); settings.directional_shadow_depth = directional_shadow.depth; settings.directional_light_buffer = get_directional_light_buffer(); - settings.vfog = rb->volumetric_fog; - settings.cluster_builder = rb->cluster_builder; - settings.rbgi = &rb->rbgi; - settings.sdfgi = rb->sdfgi; + settings.vfog = fog; + settings.cluster_builder = p_render_buffers->cluster_builder; + settings.rbgi = rbgi; + settings.sdfgi = sdfgi; settings.env = p_environment; settings.sky = &sky; settings.gi = &gi; @@ -3465,8 +2862,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) { if (p_render_data->render_buffers.is_valid()) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - if (rb->sdfgi != nullptr) { + if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { return true; } } @@ -3474,16 +2870,13 @@ bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_da } void RendererSceneRenderRD::_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) { - if (p_render_data->render_buffers.is_valid()) { - if (p_use_gi) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(rb == nullptr); - if (rb->sdfgi == nullptr) { - return; - } - - rb->sdfgi->update_probes(p_render_data->environment, sky.sky_owner.get_or_null(environment_get_sky(p_render_data->environment))); + if (p_render_data->render_buffers.is_valid() && p_use_gi) { + if (!p_render_data->render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { + return; } + + Ref<RendererRD::GI::SDFGI> sdfgi = p_render_data->render_buffers->get_custom_data(RB_SCOPE_SDFGI); + sdfgi->update_probes(p_render_data->environment, sky.sky_owner.get_or_null(environment_get_sky(p_render_data->environment))); } } @@ -3495,24 +2888,21 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo } } -void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices) { +void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer) { // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - if (p_render_data->render_buffers.is_valid() && p_use_gi) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(rb == nullptr); - if (rb->sdfgi != nullptr) { - rb->sdfgi->store_probes(); - } + if (p_render_data->render_buffers.is_valid() && p_use_gi && p_render_data->render_buffers->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = p_render_data->render_buffers->get_custom_data(RB_SCOPE_SDFGI); + sdfgi->store_probes(); } render_state.cube_shadows.clear(); render_state.shadows.clear(); render_state.directional_shadows.clear(); - Plane camera_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin); - float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier(); + Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); + float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier(); { for (int i = 0; i < render_state.render_shadow_count; i++) { LightInstance *li = light_instance_owner.get_or_null(render_state.render_shadows[i].light); @@ -3528,7 +2918,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool //cube shadows are rendered in their own way for (uint32_t i = 0; i < render_state.cube_shadows.size(); i++) { - _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); + _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.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); } if (render_state.directional_shadows.size()) { @@ -3558,11 +2948,11 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool //render directional shadows for (uint32_t i = 0; i < render_state.directional_shadows.size(); i++) { - _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false, p_render_data->render_info); + _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false, p_render_data->render_info); } //render positional shadows for (uint32_t i = 0; i < render_state.shadows.size(); i++) { - _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true, p_render_data->render_info); + _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true, p_render_data->render_info); } _render_shadow_process(); @@ -3570,7 +2960,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool //start GI if (render_gi) { - gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_vrs_slices, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); + gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances); } //Do shadow rendering (in parallel with GI) @@ -3584,16 +2974,17 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool if (p_render_data->render_buffers.is_valid() && ss_effects) { if (p_use_ssao || p_use_ssil) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); - ERR_FAIL_COND(!rb); + Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers; + ERR_FAIL_COND(rb.is_null()); + Size2i size = rb->get_internal_size(); bool invalidate_uniform_set = false; if (rb->ss_effects.linear_depth.is_null()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16_SFLOAT; tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; - tf.width = (rb->width + 1) / 2; - tf.height = (rb->height + 1) / 2; + tf.width = (size.x + 1) / 2; + tf.height = (size.y + 1) / 2; tf.mipmaps = 5; tf.array_layers = 4; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; @@ -3607,17 +2998,18 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool invalidate_uniform_set = true; } - ss_effects->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection); + RID depth_texture = rb->get_depth_texture(); + ss_effects->downsample_depth(depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, size, p_render_data->scene_data->cam_projection); } if (p_use_ssao) { // TODO make these proper stereo - _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection); + _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection); } if (p_use_ssil) { // TODO make these proper stereo - _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection, p_render_data->cam_transform); + _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform); } } @@ -3625,7 +3017,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); if (current_cluster_builder) { - current_cluster_builder->begin(p_render_data->cam_transform, p_render_data->cam_projection, !p_render_data->reflection_probe.is_valid()); + current_cluster_builder->begin(p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, !p_render_data->reflection_probe.is_valid()); } bool using_shadows = true; @@ -3636,13 +3028,13 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool } } else { //do not render reflections when rendering a reflection probe - _setup_reflections(p_render_data, *p_render_data->reflection_probes, p_render_data->cam_transform.affine_inverse(), p_render_data->environment); + _setup_reflections(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment); } uint32_t directional_light_count = 0; uint32_t positional_light_count = 0; - _setup_lights(p_render_data, *p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); - _setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse()); + _setup_lights(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); + _setup_decals(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse()); p_render_data->directional_light_count = directional_light_count; @@ -3659,48 +3051,77 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool } } if (is_volumetric_supported()) { - _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes); + _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform, p_render_data->scene_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes); } } } -void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { +void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); // getting this here now so we can direct call a bunch of things more easily - RenderBuffers *rb = nullptr; + Ref<RenderSceneBuffersRD> rb; if (p_render_buffers.is_valid()) { - rb = render_buffers_owner.get_or_null(p_render_buffers); - ERR_FAIL_COND(!rb); + rb = p_render_buffers; // cast it... + ERR_FAIL_COND(rb.is_null()); } - //assign render data - RenderDataRD render_data; + // setup scene data + RenderSceneDataRD scene_data; { - render_data.render_buffers = p_render_buffers; - // Our first camera is used by default - render_data.cam_transform = p_camera_data->main_transform; - render_data.cam_projection = p_camera_data->main_projection; - render_data.cam_orthogonal = p_camera_data->is_orthogonal; - render_data.taa_jitter = p_camera_data->taa_jitter; + scene_data.cam_transform = p_camera_data->main_transform; + scene_data.cam_projection = p_camera_data->main_projection; + scene_data.cam_orthogonal = p_camera_data->is_orthogonal; + scene_data.taa_jitter = p_camera_data->taa_jitter; - render_data.view_count = p_camera_data->view_count; + scene_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { - render_data.view_eye_offset[v] = p_camera_data->view_offset[v].origin; - render_data.view_projection[v] = p_camera_data->view_projection[v]; + scene_data.view_eye_offset[v] = p_camera_data->view_offset[v].origin; + scene_data.view_projection[v] = p_camera_data->view_projection[v]; } - render_data.prev_cam_transform = p_prev_camera_data->main_transform; - render_data.prev_cam_projection = p_prev_camera_data->main_projection; - render_data.prev_taa_jitter = p_prev_camera_data->taa_jitter; + scene_data.prev_cam_transform = p_prev_camera_data->main_transform; + scene_data.prev_cam_projection = p_prev_camera_data->main_projection; + scene_data.prev_taa_jitter = p_prev_camera_data->taa_jitter; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { - render_data.prev_view_projection[v] = p_prev_camera_data->view_projection[v]; + scene_data.prev_view_projection[v] = p_prev_camera_data->view_projection[v]; + } + + scene_data.z_near = p_camera_data->main_projection.get_z_near(); + scene_data.z_far = p_camera_data->main_projection.get_z_far(); + + // this should be the same for all cameras.. + scene_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier(); + scene_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_column(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin()); + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { + scene_data.screen_mesh_lod_threshold = 0.0; + } else { + scene_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; } - render_data.z_near = p_camera_data->main_projection.get_z_near(); - render_data.z_far = p_camera_data->main_projection.get_z_far(); + if (p_shadow_atlas.is_valid()) { + Vector2 sas = shadow_atlas_get_size(p_shadow_atlas); + scene_data.shadow_atlas_pixel_size.x = 1.0 / sas.x; + scene_data.shadow_atlas_pixel_size.y = 1.0 / sas.y; + } + { + Vector2 dss = directional_shadow_get_size(); + scene_data.directional_shadow_pixel_size.x = 1.0 / dss.x; + scene_data.directional_shadow_pixel_size.y = 1.0 / dss.y; + } + + scene_data.time = time; + scene_data.time_step = time_step; + } + + //assign render data + RenderDataRD render_data; + { + render_data.render_buffers = rb; + render_data.scene_data = &scene_data; render_data.instances = &p_instances; render_data.lights = &p_lights; @@ -3716,16 +3137,6 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.reflection_probe = p_reflection_probe; render_data.reflection_probe_pass = p_reflection_probe_pass; - // this should be the same for all cameras.. - render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier(); - render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_column(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin()); - - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { - render_data.screen_mesh_lod_threshold = 0.0; - } else { - render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold; - } - render_state.render_shadows = p_render_shadows; render_state.render_shadow_count = p_render_shadow_count; render_state.render_sdfgi_regions = p_render_sdfgi_regions; @@ -3742,23 +3153,25 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.voxel_gi_instances = ∅ } - //sdfgi first - if (rb != nullptr && rb->sdfgi != nullptr) { + // sdfgi first + if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); float exposure_normalization = 1.0; + if (p_camera_attributes.is_valid()) { exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes); } for (int i = 0; i < render_state.render_sdfgi_region_count; i++) { - rb->sdfgi->render_region(p_render_buffers, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this, exposure_normalization); + sdfgi->render_region(rb, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this, exposure_normalization); } if (render_state.sdfgi_update_data->update_static) { - rb->sdfgi->render_static_lights(&render_data, p_render_buffers, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this); + sdfgi->render_static_lights(&render_data, rb, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this); } } Color clear_color; if (p_render_buffers.is_valid()) { - clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target); + clear_color = texture_storage->render_target_get_clear_request_color(rb->get_render_target()); } else { clear_color = RSG::texture_storage->get_default_clear_color(); } @@ -3766,14 +3179,11 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData //assign render indices to voxel_gi_instances if (is_dynamic_gi_supported()) { for (uint32_t i = 0; i < (uint32_t)p_voxel_gi_instances.size(); i++) { - RendererRD::GI::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]); - if (voxel_gi_inst) { - voxel_gi_inst->render_index = i; - } + gi.voxel_gi_instance_set_render_index(p_voxel_gi_instances[i], i); } } - if (render_buffers_owner.owns(render_data.render_buffers)) { + if (rb.is_valid()) { // render_data.render_buffers == p_render_buffers so we can use our already retrieved rb current_cluster_builder = rb->cluster_builder; } else if (reflection_probe_instance_owner.owns(render_data.reflection_probe)) { @@ -3795,14 +3205,17 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_state.voxel_gi_count = 0; - if (rb != nullptr && is_dynamic_gi_supported()) { - if (rb->sdfgi) { - rb->sdfgi->update_cascades(); - rb->sdfgi->pre_process_gi(render_data.cam_transform, &render_data, this); - rb->sdfgi->update_light(); + if (rb.is_valid() && is_dynamic_gi_supported()) { + 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(scene_data.cam_transform, &render_data, this); + sdfgi->update_light(); + } } - gi.setup_voxel_gi_instances(&render_data, render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this); + gi.setup_voxel_gi_instances(&render_data, render_data.render_buffers, scene_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this); } render_state.depth_prepass_used = false; @@ -3813,33 +3226,51 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements(); } - if (rb != nullptr && rb->vrs_fb.is_valid()) { - // vrs_fb will only be valid if vrs is enabled - vrs->update_vrs_texture(rb->vrs_fb, rb->render_target); + if (rb.is_valid() && vrs) { + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->get_render_target()); + if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + RID vrs_texture = rb->get_texture(RB_SCOPE_VRS, RB_TEXTURE); + + // We use get_cache_multipass instead of get_cache_multiview because the default behavior is for + // our vrs_texture to be used as the VRS attachment. In this particular case we're writing to it + // so it needs to be set as our color attachment + + Vector<RID> textures; + textures.push_back(vrs_texture); + + Vector<RD::FramebufferPass> passes; + RD::FramebufferPass pass; + pass.color_attachments.push_back(0); + passes.push_back(pass); + + RID vrs_fb = FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, rb->get_view_count()); + + vrs->update_vrs_texture(vrs_fb, rb->get_render_target()); + } } _render_scene(&render_data, clear_color); - if (p_render_buffers.is_valid()) { - /* - _debug_draw_cluster(p_render_buffers); - _render_buffers_post_process_and_tonemap(&render_data); - */ + if (rb.is_valid()) { + _render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex); - _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex); - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) { + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb->has_custom_data(RB_SCOPE_SDFGI)) { + Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI); Vector<RID> view_rids; - for (int v = 0; v < rb->views.size(); v++) { - view_rids.push_back(rb->views[v].view_texture); + // SDFGI renders at internal resolution, need to check if our debug correctly supports outputting upscaled. + Size2i size = rb->get_internal_size(); + RID source_texture = rb->get_internal_texture(); + for (uint32_t v = 0; v < rb->get_view_count(); v++) { + view_rids.push_back(rb->get_internal_texture(v)); } - rb->sdfgi->debug_draw(render_data.view_count, render_data.view_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture, view_rids); + sdfgi->debug_draw(scene_data.view_count, scene_data.view_projection, scene_data.cam_transform, size.x, size.y, rb->get_render_target(), source_texture, view_rids); } } } -void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) { +void RendererSceneRenderRD::_debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers) { if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) { RS::ViewportDebugDraw dd = get_debug_draw_mode(); @@ -4062,24 +3493,7 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, } bool RendererSceneRenderRD::free(RID p_rid) { - if (render_buffers_owner.owns(p_rid)) { - RenderBuffers *rb = render_buffers_owner.get_or_null(p_rid); - _free_render_buffer_data(rb); - memdelete(rb->data); - if (rb->sdfgi) { - rb->sdfgi->erase(); - memdelete(rb->sdfgi); - rb->sdfgi = nullptr; - } - if (rb->volumetric_fog) { - memdelete(rb->volumetric_fog); - rb->volumetric_fog = nullptr; - } - if (rb->cluster_builder) { - memdelete(rb->cluster_builder); - } - render_buffers_owner.free(p_rid); - } else if (is_environment(p_rid)) { + if (is_environment(p_rid)) { environment_free(p_rid); } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) { RSG::camera_attributes->camera_attributes_free(p_rid); @@ -4175,7 +3589,7 @@ float RendererSceneRenderRD::screen_space_roughness_limiter_get_limit() const { return screen_space_roughness_limiter_limit; } -TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) { +TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tf.width = p_image_size.width; // Always 64x64 @@ -4430,6 +3844,7 @@ void RendererSceneRenderRD::init() { tone_mapper = memnew(RendererRD::ToneMapper); vrs = memnew(RendererRD::VRS); if (can_use_storage) { + fsr = memnew(RendererRD::FSR); ss_effects = memnew(RendererRD::SSEffects); } } @@ -4447,6 +3862,9 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { if (vrs) { memdelete(vrs); } + if (fsr) { + memdelete(fsr); + } if (ss_effects) { memdelete(ss_effects); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 70109b29da..b3a355f42f 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -37,36 +37,23 @@ #include "servers/rendering/renderer_rd/cluster_builder_rd.h" #include "servers/rendering/renderer_rd/effects/bokeh_dof.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" +#include "servers/rendering/renderer_rd/effects/fsr.h" #include "servers/rendering/renderer_rd/effects/ss_effects.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" #include "servers/rendering/renderer_rd/effects/vrs.h" #include "servers/rendering/renderer_rd/environment/fog.h" #include "servers/rendering/renderer_rd/environment/gi.h" #include "servers/rendering/renderer_rd/environment/sky.h" +#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" struct RenderDataRD { - RID render_buffers; - - Transform3D cam_transform; - Projection cam_projection; - Vector2 taa_jitter; - bool cam_orthogonal = false; - - // For stereo rendering - uint32_t view_count = 1; - Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; - Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; - - Transform3D prev_cam_transform; - Projection prev_cam_projection; - Vector2 prev_taa_jitter; - Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; - - float z_near = 0.0; - float z_far = 0.0; + Ref<RenderSceneBuffersRD> render_buffers; + RenderSceneDataRD *scene_data; const PagedArray<RenderGeometryInstance *> *instances = nullptr; const PagedArray<RID> *lights = nullptr; @@ -82,10 +69,6 @@ struct RenderDataRD { RID reflection_probe; int reflection_probe_pass = 0; - float lod_distance_multiplier = 0.0; - Plane lod_camera_plane; - float screen_mesh_lod_threshold = 0.0; - RID cluster_buffer; uint32_t cluster_size = 0; uint32_t cluster_max_elements = 0; @@ -104,15 +87,12 @@ protected: RendererRD::BokehDOF *bokeh_dof = nullptr; RendererRD::CopyEffects *copy_effects = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; + RendererRD::FSR *fsr = nullptr; RendererRD::VRS *vrs = nullptr; double time = 0.0; double time_step = 0.0; - struct RenderBufferData { - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0; - virtual ~RenderBufferData() {} - }; - virtual RenderBufferData *_create_render_buffer_data() = 0; + virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; void _setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows); void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform); @@ -127,31 +107,28 @@ protected: virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) = 0; virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; - virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0; + virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0; - void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); - void _debug_draw_cluster(RID p_render_buffers); - - RenderBufferData *render_buffers_get_data(RID p_render_buffers); + void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); + void _debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers); virtual void _base_uniforms_changed() = 0; - virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0; - virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0; + virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; + virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0; - void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); - void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive); - void _process_sss(RID p_render_buffers, const Projection &p_camera); - void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform); + void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection); + void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive); + void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera); + void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform); - void _copy_framebuffer_to_ssil(RID p_render_buffers); - void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far); + void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers); bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi); - void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices); + void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer); void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data); void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data); @@ -424,131 +401,22 @@ private: bool use_physical_light_units = false; - /* RENDER BUFFERS */ + /* Cluster builder */ ClusterBuilderSharedDataRD cluster_builder_shared; ClusterBuilderRD *current_cluster_builder = nullptr; - struct RenderBuffers { - RenderBufferData *data = nullptr; - int internal_width = 0; - int internal_height = 0; - int width = 0; - int height = 0; - float fsr_sharpness = 0.2f; - RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED; - RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; - bool use_taa = false; - bool use_debanding = false; - uint32_t view_count = 1; - - RID render_target; - - uint64_t auto_exposure_version = 1; - - RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0] - RID internal_texture; //main texture for rendering to, must be filled after done rendering - RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling) - RID depth_texture; //main depth texture - RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! - RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling) - RID vrs_texture; // texture for vrs. - RID vrs_fb; // framebuffer to write to our vrs texture - - // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images) - struct View { - RID view_texture; // texture slice for this view/layer - RID view_depth; // depth slice for this view/layer - RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! - }; - Vector<View> views; - - RendererRD::GI::SDFGI *sdfgi = nullptr; - RendererRD::GI::RenderBuffersGI rbgi; - RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr; - - ClusterBuilderRD *cluster_builder = nullptr; - - //built-in textures used for ping pong image processing and blurring - struct Blur { - RID texture; - - struct Mipmap { - RID texture; - int width; - int height; - - // only used on mobile renderer - RID fb; - RID half_texture; - RID half_fb; - }; - - struct Layer { - Vector<Mipmap> mipmaps; - }; - - Vector<Layer> layers; - }; - - Blur blur[2]; //the second one starts from the first mipmap - - struct WeightBuffers { - RID weight; - RID fb; // FB with both texture and weight writing into one level lower - }; - - // 2 full size, 2 half size - WeightBuffers weight_buffers[4]; // Only used in raster - - RID depth_back_texture; - RID depth_back_fb; // only used on mobile - - struct Luminance { - Vector<RID> reduce; - RID current; - - // used only on mobile renderer - Vector<RID> fb; - RID current_fb; - } luminance; - - struct SSEffects { - RID linear_depth; - Vector<RID> linear_depth_slices; - - RID downsample_uniform_set; - - Projection last_frame_projection; - Transform3D last_frame_transform; - - RendererRD::SSEffects::SSAORenderBuffers ssao; - RendererRD::SSEffects::SSILRenderBuffers ssil; - } ss_effects; + /* RENDER BUFFERS */ - RendererRD::SSEffects::SSRRenderBuffers ssr; + void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb); - struct TAA { - RID history; - RID temp; - RID prev_velocity; // Last frame velocity buffer - } taa; - }; + void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer); /* GI */ bool screen_space_roughness_limiter = false; float screen_space_roughness_limiter_amount = 0.25; float screen_space_roughness_limiter_limit = 0.18; - mutable RID_Owner<RenderBuffers> render_buffers_owner; - - void _free_render_buffer_data(RenderBuffers *rb); - void _allocate_blur_textures(RenderBuffers *rb); - void _allocate_depth_backbuffer_textures(RenderBuffers *rb); - void _allocate_luminance_textures(RenderBuffers *rb); - - void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer); - /* Cluster */ struct Cluster { @@ -710,13 +578,6 @@ private: uint64_t scene_pass = 0; uint64_t shadow_atlas_realloc_tolerance_msec = 500; - /* !BAS! is this used anywhere? - struct SDFGICosineNeighbour { - uint32_t neighbour; - float weight; - }; - */ - uint32_t max_cluster_elements = 512; void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr); @@ -727,15 +588,22 @@ private: uint32_t volumetric_fog_depth = 128; bool volumetric_fog_filter_active = true; - void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); + void _update_volumetric_fog(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); public: static RendererSceneRenderRD *get_singleton() { return singleton; } + /* Cluster builder */ + ClusterBuilderSharedDataRD *get_cluster_builder_shared() { return &cluster_builder_shared; } + /* GI */ RendererRD::GI *get_gi() { return &gi; } + /* SKY */ + + RendererRD::SkyRD *get_sky() { return &sky; } + /* SHADOW ATLAS API */ virtual RID shadow_atlas_create() override; @@ -774,10 +642,10 @@ public: /* SDFGI UPDATE */ - virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override; - virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const override; - virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override; - virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override; + virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override; + virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override; + virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override; + virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override; RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; } /* SKY API */ @@ -1071,42 +939,14 @@ public: virtual float _render_buffers_get_luminance_multiplier(); virtual RD::DataFormat _render_buffers_get_color_format(); virtual bool _render_buffers_can_be_storage(); - virtual RID render_buffers_create() override; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; + virtual Ref<RenderSceneBuffers> render_buffers_create() override; virtual void gi_set_use_half_resolution(bool p_enable) override; - RID render_buffers_get_depth_texture(RID p_render_buffers); - RID render_buffers_get_ao_texture(RID p_render_buffers); - RID render_buffers_get_ssil_texture(RID p_render_buffers); - RID render_buffers_get_back_buffer_texture(RID p_render_buffers); - RID render_buffers_get_back_depth_texture(RID p_render_buffers); - RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers); RID render_buffers_get_default_voxel_gi_buffer(); - RID render_buffers_get_gi_ambient_texture(RID p_render_buffers); - RID render_buffers_get_gi_reflection_texture(RID p_render_buffers); - - uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const; - bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const; - RID render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const; - Vector3 render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const; - Vector3i render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const; - float render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const; - float render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const; - uint32_t render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const; - uint32_t render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const; - bool render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const; - float render_buffers_get_sdfgi_energy(RID p_render_buffers) const; - RID render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const; - - bool render_buffers_has_volumetric_fog(RID p_render_buffers) const; - RID render_buffers_get_volumetric_fog_texture(RID p_render_buffers); - RID render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers); - float render_buffers_get_volumetric_fog_end(RID p_render_buffers); - float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers); virtual void update_uniform_sets(){}; - virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; + virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; @@ -1183,7 +1023,7 @@ public: int get_roughness_layers() const; bool is_using_radiance_cubemap_array() const; - virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override; + virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) override; virtual bool free(RID p_rid) override; diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub index d352743908..5405985741 100644 --- a/servers/rendering/renderer_rd/shaders/SCsub +++ b/servers/rendering/renderer_rd/shaders/SCsub @@ -18,3 +18,5 @@ if "RD_GLSL" in env["BUILDERS"]: SConscript("effects/SCsub") SConscript("environment/SCsub") +SConscript("forward_clustered/SCsub") +SConscript("forward_mobile/SCsub") diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl index bdf84bb03a..fe770ac065 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl @@ -186,6 +186,7 @@ void main() { uv += pixel_size * 0.5; //half pixel to read centers vec4 color = texture(color_texture, uv); + float initial_blur = color.a; float accum = 1.0; float radius = params.blur_scale; @@ -193,8 +194,8 @@ void main() { vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius; vec4 sample_color = texture(color_texture, suv); float sample_size = abs(sample_color.a); - if (sample_color.a > color.a) { - sample_size = clamp(sample_size, 0.0, abs(color.a) * 2.0); + if (sample_color.a > initial_blur) { + sample_size = clamp(sample_size, 0.0, abs(initial_blur) * 2.0); } float m = smoothstep(radius - 0.5, radius + 0.5, sample_size); diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl index a2bdc2e90e..1b487835d2 100644 --- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl @@ -221,12 +221,9 @@ void main() { vec4 sample_color = texture(source_color, uv_adj); sample_color.a = texture(source_weight, uv_adj).r; - float limit; - - if (sample_color.a < color.a) { - limit = abs(sample_color.a); - } else { - limit = abs(color.a); + float limit = abs(sample_color.a); + if (sample_color.a > color.a) { + limit = clamp(limit, 0.0, abs(color.a) * 2.0); } limit -= DEPTH_GAP; diff --git a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl index c8eb78a2f0..c8eb78a2f0 100644 --- a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl index 246ef81cb2..9f86643e52 100644 --- a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl @@ -30,12 +30,7 @@ layout(push_constant, std430) uniform Params { bool orthogonal; float filter_mipmap_levels; bool use_half_res; - uint metallic_mask; - uint view_index; - uint pad1; - uint pad2; - uint pad3; } params; @@ -167,7 +162,7 @@ void main() { if (depth > z_to) { // if depth was surpassed - if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far) { + if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far * 0.95) { // check the depth tolerance and far clip // check that normal is valid found = true; @@ -231,18 +226,20 @@ void main() { } } - // Isn't this going to be overwritten after our endif? - final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size)); - imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8 #endif // MODE_ROUGH final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend); - //change blend by metallic - vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask); - final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0)); + // Schlick term. + float metallic = texelFetch(source_metallic, ssC << 1, 0).w; + float f0 = mix(0.04, 1.0, metallic); // Assume a "specular" amount of 0.5 + normal.y = -normal.y; + float m = clamp(1.0 - dot(normalize(normal), -view_dir), 0.0, 1.0); + float m2 = m * m; + m = m2 * m2 * m; // pow(m,5) + final_color.a *= f0 + (1.0 - f0) * m; // Fresnel Schlick term. imageStore(ssr_image, ssC, final_color); diff --git a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl index fb35d3cde6..fb35d3cde6 100644 --- a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl index b0a0839836..b0a0839836 100644 --- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl diff --git a/servers/rendering/renderer_rd/shaders/environment/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl index 7a0b2af3ce..d523461600 100644 --- a/servers/rendering/renderer_rd/shaders/environment/sky.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl @@ -83,20 +83,23 @@ layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUnifor global_shader_uniforms; layout(set = 0, binding = 2, std140) uniform SceneData { - bool volumetric_fog_enabled; - float volumetric_fog_inv_length; - float volumetric_fog_detail_spread; - - float fog_aerial_perspective; - - vec3 fog_light_color; - float fog_sun_scatter; - - bool fog_enabled; - float fog_density; - - float z_far; - uint directional_light_count; + bool volumetric_fog_enabled; // 4 - 4 + float volumetric_fog_inv_length; // 4 - 8 + float volumetric_fog_detail_spread; // 4 - 12 + float volumetric_fog_sky_affect; // 4 - 16 + + bool fog_enabled; // 4 - 20 + float fog_sky_affect; // 4 - 24 + float fog_density; // 4 - 28 + float fog_sun_scatter; // 4 - 32 + + vec3 fog_light_color; // 12 - 44 + float fog_aerial_perspective; // 4 - 48 + + float z_far; // 4 - 52 + uint directional_light_count; // 4 - 56 + uint pad1; // 4 - 60 + uint pad2; // 4 - 64 } scene_data; @@ -150,6 +153,15 @@ layout(set = 3, binding = 0) uniform texture3D volumetric_fog_texture; layout(location = 0) out vec4 frag_color; +#ifdef USE_DEBANDING +// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare +vec3 interleaved_gradient_noise(vec2 pos) { + const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f); + float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0; + return vec3(res, -res, res) / 255.0; +} +#endif + vec4 volumetric_fog_process(vec2 screen_uv) { vec3 fog_pos = vec3(screen_uv, 1.0); @@ -169,9 +181,7 @@ vec4 fog_process(vec3 view, vec3 sky_color) { } } - float fog_amount = clamp(1.0 - exp(-scene_data.z_far * scene_data.fog_density), 0.0, 1.0); - - return vec4(fog_color, fog_amount); + return vec4(fog_color, 1.0); } void main() { @@ -228,12 +238,12 @@ void main() { // Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky. if (scene_data.fog_enabled) { vec4 fog = fog_process(cube_normal, frag_color.rgb); - frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); + frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.fog_sky_affect); } if (scene_data.volumetric_fog_enabled) { vec4 fog = volumetric_fog_process(uv); - frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); + frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.volumetric_fog_sky_affect); } if (custom_fog.a > 0.0) { @@ -251,4 +261,8 @@ void main() { // For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer. // For both mobile and clustered, we also bake in the exposure value for the environment and camera. frag_color.rgb = frag_color.rgb * params.luminance_multiplier; + +#ifdef USE_DEBANDING + frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy); +#endif } diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub new file mode 100644 index 0000000000..741da8fe69 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +Import("env") + +if "RD_GLSL" in env["BUILDERS"]: + # find all include files + gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + + # find all shader code(all glsl files excluding our include files) + glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] + + # make sure we recompile shaders if include files change + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) + + # compile shaders + for glsl_file in glsl_files: + env.RD_GLSL(glsl_file) diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 26b96b358f..d41474118d 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -129,7 +129,7 @@ invariant gl_Position; #GLOBALS -void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) { +void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) { vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) color_interp = color_attrib; @@ -208,7 +208,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc } } - uint offset = stride * gl_InstanceIndex; + uint offset = stride * (gl_InstanceIndex + multimesh_offset); if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); @@ -326,10 +326,6 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc vertex_interp = vertex; -#ifdef MOTION_VECTORS - screen_pos = projection_matrix * vec4(vertex_interp, 1.0); -#endif - #ifdef NORMAL_USED normal_interp = normal; #endif @@ -367,6 +363,10 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc gl_Position = projection_matrix * vec4(vertex_interp, 1.0); #endif +#ifdef MOTION_VECTORS + screen_pos = gl_Position; +#endif + #ifdef MODE_RENDER_DEPTH if (scene_data.pancake_shadows) { if (gl_Position.z <= 0.00001) { @@ -397,13 +397,13 @@ void main() { mat4 model_matrix = instances.data[instance_index].transform; #if defined(MOTION_VECTORS) global_time = scene_data_block.prev_data.time; - vertex_shader(instance_index, is_multimesh, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position); + vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position); global_time = scene_data_block.data.time; - vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position); + vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position); #else global_time = scene_data_block.data.time; vec4 screen_position; - vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position); + vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position); #endif } @@ -553,7 +553,7 @@ layout(location = 0) out vec4 frag_color; layout(location = 2) out vec2 motion_vector; #endif -#include "scene_forward_aa_inc.glsl" +#include "../scene_forward_aa_inc.glsl" #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) @@ -562,20 +562,20 @@ layout(location = 2) out vec2 motion_vector; #define SPECULAR_SCHLICK_GGX #endif -#include "scene_forward_lights_inc.glsl" +#include "../scene_forward_lights_inc.glsl" -#include "scene_forward_gi_inc.glsl" +#include "../scene_forward_gi_inc.glsl" #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) #ifndef MODE_RENDER_DEPTH vec4 volumetric_fog_process(vec2 screen_uv, float z) { - vec3 fog_pos = vec3(screen_uv, z * scene_data_block.data.volumetric_fog_inv_length); + vec3 fog_pos = vec3(screen_uv, z * implementation_data.volumetric_fog_inv_length); if (fog_pos.z < 0.0) { return vec4(0.0); } else if (fog_pos.z < 1.0) { - fog_pos.z = pow(fog_pos.z, scene_data_block.data.volumetric_fog_detail_spread); + fog_pos.z = pow(fog_pos.z, implementation_data.volumetric_fog_detail_spread); } return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos); @@ -821,7 +821,7 @@ void fragment_shader(in SceneData scene_data) { fog = fog_process(vertex); } - if (scene_data.volumetric_fog_enabled) { + if (implementation_data.volumetric_fog_enabled) { vec4 volumetric_fog = volumetric_fog_process(screen_uv, -vertex.z); if (scene_data.fog_enabled) { //must use the full blending equation here to blend fogs @@ -849,8 +849,8 @@ void fragment_shader(in SceneData scene_data) { #ifndef MODE_RENDER_DEPTH - uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> scene_data.cluster_shift; - uint cluster_offset = (scene_data.cluster_width * cluster_pos.y + cluster_pos.x) * (scene_data.max_cluster_element_count_div_32 + 32); + uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> implementation_data.cluster_shift; + uint cluster_offset = (implementation_data.cluster_width * cluster_pos.y + cluster_pos.x) * (implementation_data.max_cluster_element_count_div_32 + 32); uint cluster_z = uint(clamp((-vertex.z / scene_data.z_far) * 32.0, 0.0, 31.0)); @@ -860,14 +860,14 @@ void fragment_shader(in SceneData scene_data) { { // process decals - uint cluster_decal_offset = cluster_offset + scene_data.cluster_type_size * 2; + uint cluster_decal_offset = cluster_offset + implementation_data.cluster_type_size * 2; uint item_min; uint item_max; uint item_from; uint item_to; - cluster_get_item_range(cluster_decal_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); + cluster_get_item_range(cluster_decal_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); #ifdef USE_SUBGROUPS item_from = subgroupBroadcastFirst(subgroupMin(item_from)); @@ -1256,7 +1256,7 @@ void fragment_shader(in SceneData scene_data) { vec2 coord; - if (scene_data.gi_upscale_for_msaa) { + if (implementation_data.gi_upscale_for_msaa) { vec2 base_coord = screen_uv; vec2 closest_coord = base_coord; #ifdef USE_MULTIVIEW @@ -1298,10 +1298,10 @@ void fragment_shader(in SceneData scene_data) { } #endif // !USE_LIGHTMAP - if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) { + if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) { float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; ao = min(ao, ssao); - ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect); + ao_light_affect = mix(ao_light_affect, max(ao_light_affect, implementation_data.ssao_light_affect), implementation_data.ssao_ao_affect); } { // process reflections @@ -1309,14 +1309,14 @@ void fragment_shader(in SceneData scene_data) { vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - uint cluster_reflection_offset = cluster_offset + scene_data.cluster_type_size * 3; + uint cluster_reflection_offset = cluster_offset + implementation_data.cluster_type_size * 3; uint item_min; uint item_max; uint item_from; uint item_to; - cluster_get_item_range(cluster_reflection_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); + cluster_get_item_range(cluster_reflection_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); #ifdef USE_SUBGROUPS item_from = subgroupBroadcastFirst(subgroupMin(item_from)); @@ -1380,7 +1380,7 @@ void fragment_shader(in SceneData scene_data) { // convert ao to direct light ao ao = mix(1.0, ao, ao_light_affect); - if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) { + if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) { vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0); ambient_light *= 1.0 - ssil.a; ambient_light += ssil.rgb * albedo.rgb; @@ -1748,7 +1748,7 @@ void fragment_shader(in SceneData scene_data) { uint item_from; uint item_to; - cluster_get_item_range(cluster_omni_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); + cluster_get_item_range(cluster_omni_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); #ifdef USE_SUBGROUPS item_from = subgroupBroadcastFirst(subgroupMin(item_from)); @@ -1812,14 +1812,14 @@ void fragment_shader(in SceneData scene_data) { { //spot lights - uint cluster_spot_offset = cluster_offset + scene_data.cluster_type_size; + uint cluster_spot_offset = cluster_offset + implementation_data.cluster_type_size; uint item_min; uint item_max; uint item_from; uint item_to; - cluster_get_item_range(cluster_spot_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); + cluster_get_item_range(cluster_spot_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to); #ifdef USE_SUBGROUPS item_from = subgroupBroadcastFirst(subgroupMin(item_from)); @@ -1909,8 +1909,8 @@ void fragment_shader(in SceneData scene_data) { #ifdef MODE_RENDER_SDF { - vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz; - ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size)); + vec3 local_pos = (implementation_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz; + ivec3 grid_pos = implementation_data.sdf_offset + ivec3(local_pos * vec3(implementation_data.sdf_size)); uint albedo16 = 0x1; //solid flag albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11; diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl index 45484b8c47..e8e2dce990 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl @@ -17,8 +17,9 @@ #extension GL_EXT_multiview : enable #endif -#include "cluster_data_inc.glsl" -#include "decal_data_inc.glsl" +#include "../cluster_data_inc.glsl" +#include "../decal_data_inc.glsl" +#include "../scene_data_inc.glsl" #if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_VOXEL_GI) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) #ifndef NORMAL_USED @@ -29,8 +30,8 @@ layout(push_constant, std430) uniform DrawCall { uint instance_index; uint uv_offset; - uint pad0; - uint pad1; + uint multimesh_motion_vectors_current_offset; + uint multimesh_motion_vectors_previous_offset; } draw_call; @@ -38,7 +39,7 @@ draw_call; /* Set 0: Base Pass (never changes) */ -#include "light_data_inc.glsl" +#include "../light_data_inc.glsl" #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 @@ -175,62 +176,27 @@ sdfgi; /* Set 1: Render Pass (changes per render pass) */ -struct SceneData { - mat4 projection_matrix; - mat4 inv_projection_matrix; - mat4 inv_view_matrix; - mat4 view_matrix; - - // only used for multiview - mat4 projection_matrix_view[MAX_VIEWS]; - mat4 inv_projection_matrix_view[MAX_VIEWS]; - vec4 eye_offset[MAX_VIEWS]; - - vec2 viewport_size; - vec2 screen_pixel_size; +layout(set = 1, binding = 0, std140) uniform SceneDataBlock { + SceneData data; + SceneData prev_data; +} +scene_data_block; +struct ImplementationData { uint cluster_shift; uint cluster_width; uint cluster_type_size; uint max_cluster_element_count_div_32; - // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted. - vec4 directional_penumbra_shadow_kernel[32]; - vec4 directional_soft_shadow_kernel[32]; - vec4 penumbra_shadow_kernel[32]; - vec4 soft_shadow_kernel[32]; - - vec4 ambient_light_color_energy; - - float ambient_color_sky_mix; - bool use_ambient_light; - bool use_ambient_cubemap; - bool use_reflection_cubemap; - - mat3 radiance_inverse_xform; - - vec2 shadow_atlas_pixel_size; - vec2 directional_shadow_pixel_size; - - uint directional_light_count; - float dual_paraboloid_side; - float z_far; - float z_near; - uint ss_effects_flags; float ssao_light_affect; float ssao_ao_affect; - bool roughness_limiter_enabled; - - float roughness_limiter_amount; - float roughness_limiter_limit; - float opaque_prepass_threshold; - uint roughness_limiter_pad; + uint pad1; mat4 sdf_to_bounds; ivec3 sdf_offset; - bool material_uv2_mode; + uint pad2; ivec3 sdf_size; bool gi_upscale_for_msaa; @@ -239,31 +205,14 @@ struct SceneData { float volumetric_fog_inv_length; float volumetric_fog_detail_spread; uint volumetric_fog_pad; - - bool fog_enabled; - float fog_density; - float fog_height; - float fog_height_density; - - vec3 fog_light_color; - float fog_sun_scatter; - - float fog_aerial_perspective; - - float time; - float reflection_multiplier; // one normally, zero when rendering reflections - - bool pancake_shadows; - vec2 taa_jitter; - float emissive_exposure_normalization; - float IBL_exposure_normalization; }; -layout(set = 1, binding = 0, std140) uniform SceneDataBlock { - SceneData data; - SceneData prev_data; +layout(set = 1, binding = 1, std140) uniform ImplementationDataBlock { + ImplementationData data; } -scene_data_block; +implementation_data_block; + +#define implementation_data implementation_data_block.data struct InstanceData { mat4 transform; @@ -275,42 +224,42 @@ struct InstanceData { vec4 lightmap_uv_scale; }; -layout(set = 1, binding = 1, std430) buffer restrict readonly InstanceDataBuffer { +layout(set = 1, binding = 2, std430) buffer restrict readonly InstanceDataBuffer { InstanceData data[]; } instances; #ifdef USE_RADIANCE_CUBEMAP_ARRAY -layout(set = 1, binding = 2) uniform textureCubeArray radiance_cubemap; +layout(set = 1, binding = 3) uniform textureCubeArray radiance_cubemap; #else -layout(set = 1, binding = 2) uniform textureCube radiance_cubemap; +layout(set = 1, binding = 3) uniform textureCube radiance_cubemap; #endif -layout(set = 1, binding = 3) uniform textureCubeArray reflection_atlas; +layout(set = 1, binding = 4) uniform textureCubeArray reflection_atlas; -layout(set = 1, binding = 4) uniform texture2D shadow_atlas; +layout(set = 1, binding = 5) uniform texture2D shadow_atlas; -layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas; +layout(set = 1, binding = 6) uniform texture2D directional_shadow_atlas; -layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; +layout(set = 1, binding = 7) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; -layout(set = 1, binding = 7) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; +layout(set = 1, binding = 8) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; -layout(set = 1, binding = 8, std430) buffer restrict readonly ClusterBuffer { +layout(set = 1, binding = 9, std430) buffer restrict readonly ClusterBuffer { uint data[]; } cluster_buffer; #ifdef MODE_RENDER_SDF -layout(r16ui, set = 1, binding = 9) uniform restrict writeonly uimage3D albedo_volume_grid; -layout(r32ui, set = 1, binding = 10) uniform restrict writeonly uimage3D emission_grid; -layout(r32ui, set = 1, binding = 11) uniform restrict writeonly uimage3D emission_aniso_grid; -layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid; +layout(r16ui, set = 1, binding = 10) uniform restrict writeonly uimage3D albedo_volume_grid; +layout(r32ui, set = 1, binding = 11) uniform restrict writeonly uimage3D emission_grid; +layout(r32ui, set = 1, binding = 12) uniform restrict writeonly uimage3D emission_aniso_grid; +layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid; //still need to be present for shaders that use it, so remap them to something #define depth_buffer shadow_atlas @@ -319,21 +268,21 @@ layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid; #else -layout(set = 1, binding = 9) uniform texture2D depth_buffer; -layout(set = 1, binding = 10) uniform texture2D color_buffer; +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 = 11) uniform texture2DArray normal_roughness_buffer; -layout(set = 1, binding = 13) uniform texture2DArray ambient_buffer; -layout(set = 1, binding = 14) uniform texture2DArray reflection_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; #else // USE_MULTIVIEW -layout(set = 1, binding = 11) uniform texture2D normal_roughness_buffer; -layout(set = 1, binding = 13) uniform texture2D ambient_buffer; -layout(set = 1, binding = 14) uniform texture2D reflection_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; #endif -layout(set = 1, binding = 12) uniform texture2D ao_buffer; -layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture; -layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades; +layout(set = 1, binding = 13) uniform texture2D ao_buffer; +layout(set = 1, binding = 16) uniform texture2DArray sdfgi_lightprobe_texture; +layout(set = 1, binding = 17) uniform texture3D sdfgi_occlusion_cascades; struct VoxelGIData { mat4 xform; // 64 - 64 @@ -350,14 +299,14 @@ struct VoxelGIData { float exposure_normalization; // 4 - 112 }; -layout(set = 1, binding = 17, std140) uniform VoxelGIs { +layout(set = 1, binding = 18, std140) uniform VoxelGIs { VoxelGIData data[MAX_VOXEL_GI_INSTANCES]; } voxel_gi_instances; -layout(set = 1, binding = 18) uniform texture3D volumetric_fog_texture; +layout(set = 1, binding = 19) uniform texture3D volumetric_fog_texture; -layout(set = 1, binding = 19) uniform texture2D ssil_buffer; +layout(set = 1, binding = 20) uniform texture2D ssil_buffer; #endif diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub new file mode 100644 index 0000000000..741da8fe69 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +Import("env") + +if "RD_GLSL" in env["BUILDERS"]: + # find all include files + gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + + # find all shader code(all glsl files excluding our include files) + glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] + + # make sure we recompile shaders if include files change + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) + + # compile shaders + for glsl_file in glsl_files: + env.RD_GLSL(glsl_file) diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index 5a5ada7231..a109fd4d75 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -101,7 +101,7 @@ layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms #ifdef MODE_DUAL_PARABOLOID -layout(location = 8) out highp float dp_clip; +layout(location = 9) out highp float dp_clip; #endif @@ -450,7 +450,7 @@ layout(location = 6) mediump in vec3 binormal_interp; #ifdef MODE_DUAL_PARABOLOID -layout(location = 8) highp in float dp_clip; +layout(location = 9) highp in float dp_clip; #endif @@ -519,7 +519,7 @@ layout(location = 0) out mediump vec4 frag_color; #endif // RENDER DEPTH -#include "scene_forward_aa_inc.glsl" +#include "../scene_forward_aa_inc.glsl" #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) @@ -528,7 +528,7 @@ layout(location = 0) out mediump vec4 frag_color; #define SPECULAR_SCHLICK_GGX #endif -#include "scene_forward_lights_inc.glsl" +#include "../scene_forward_lights_inc.glsl" #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl index 3a9c52f5bc..5e4999fa0f 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl @@ -5,7 +5,8 @@ #extension GL_EXT_multiview : enable #endif -#include "decal_data_inc.glsl" +#include "../decal_data_inc.glsl" +#include "../scene_data_inc.glsl" #if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED) #ifndef NORMAL_USED @@ -32,7 +33,7 @@ draw_call; /* Set 0: Base Pass (never changes) */ -#include "light_data_inc.glsl" +#include "../light_data_inc.glsl" #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 @@ -127,75 +128,9 @@ global_shader_uniforms; /* Set 1: Render Pass (changes per render pass) */ -struct SceneData { - highp mat4 projection_matrix; - highp mat4 inv_projection_matrix; - highp mat4 inv_view_matrix; - highp mat4 view_matrix; - - // only used for multiview - highp mat4 projection_matrix_view[MAX_VIEWS]; - highp mat4 inv_projection_matrix_view[MAX_VIEWS]; - highp vec4 eye_offset[MAX_VIEWS]; - - highp vec2 viewport_size; - highp vec2 screen_pixel_size; - - // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted. - highp vec4 directional_penumbra_shadow_kernel[32]; - highp vec4 directional_soft_shadow_kernel[32]; - highp vec4 penumbra_shadow_kernel[32]; - highp vec4 soft_shadow_kernel[32]; - - mediump vec4 ambient_light_color_energy; - - mediump float ambient_color_sky_mix; - bool use_ambient_light; - bool use_ambient_cubemap; - bool use_reflection_cubemap; - - mediump mat3 radiance_inverse_xform; - - highp vec2 shadow_atlas_pixel_size; - highp vec2 directional_shadow_pixel_size; - - uint directional_light_count; - mediump float dual_paraboloid_side; - highp float z_far; - highp float z_near; - - bool ssao_enabled; - mediump float ssao_light_affect; - mediump float ssao_ao_affect; - bool roughness_limiter_enabled; - - mediump float roughness_limiter_amount; - mediump float roughness_limiter_limit; - mediump float opaque_prepass_threshold; - uint roughness_limiter_pad; - - bool fog_enabled; - highp float fog_density; - highp float fog_height; - highp float fog_height_density; - - mediump vec3 fog_light_color; - mediump float fog_sun_scatter; - - mediump float fog_aerial_perspective; - bool material_uv2_mode; - - highp float time; - mediump float reflection_multiplier; // one normally, zero when rendering reflections - - bool pancake_shadows; - float emissive_exposure_normalization; - float IBL_exposure_normalization; - uint pad3; -}; - layout(set = 1, binding = 0, std140) uniform SceneDataBlock { SceneData data; + SceneData prev_data; } scene_data_block; diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl new file mode 100644 index 0000000000..048257e9ef --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl @@ -0,0 +1,69 @@ +// Scene data stores all our 3D rendering globals for a frame such as our matrices +// where this information is independent of the different RD implementations. +// This enables us to use this UBO in our main scene render shaders but also in +// effects that need access to this data. + +struct SceneData { + highp mat4 projection_matrix; + highp mat4 inv_projection_matrix; + highp mat4 inv_view_matrix; + highp mat4 view_matrix; + + // only used for multiview + highp mat4 projection_matrix_view[MAX_VIEWS]; + highp mat4 inv_projection_matrix_view[MAX_VIEWS]; + highp vec4 eye_offset[MAX_VIEWS]; + + highp vec2 viewport_size; + highp vec2 screen_pixel_size; + + // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted. + highp vec4 directional_penumbra_shadow_kernel[32]; + highp vec4 directional_soft_shadow_kernel[32]; + highp vec4 penumbra_shadow_kernel[32]; + highp vec4 soft_shadow_kernel[32]; + + mediump mat3 radiance_inverse_xform; + + mediump vec4 ambient_light_color_energy; + + mediump float ambient_color_sky_mix; + bool use_ambient_light; + bool use_ambient_cubemap; + bool use_reflection_cubemap; + + highp vec2 shadow_atlas_pixel_size; + highp vec2 directional_shadow_pixel_size; + + uint directional_light_count; + mediump float dual_paraboloid_side; + highp float z_far; + highp float z_near; + + bool roughness_limiter_enabled; + mediump float roughness_limiter_amount; + mediump float roughness_limiter_limit; + mediump float opaque_prepass_threshold; + + bool fog_enabled; + highp float fog_density; + highp float fog_height; + highp float fog_height_density; + + mediump vec3 fog_light_color; + mediump float fog_sun_scatter; + + mediump float fog_aerial_perspective; + highp float time; + mediump float reflection_multiplier; // one normally, zero when rendering reflections + bool material_uv2_mode; + + vec2 taa_jitter; + float emissive_exposure_normalization; + float IBL_exposure_normalization; + + bool pancake_shadows; + uint pad1; + uint pad2; + uint pad3; +}; 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 4e6e29b315..2fba1351f7 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -97,11 +97,12 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance #if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + // Energy conserving lambert wrap shader. + // https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/ + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI); #elif defined(DIFFUSE_TOON) - diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); + diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI); #elif defined(DIFFUSE_BURLEY) diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index fa8406e7a1..b36a028f04 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -954,7 +954,7 @@ void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringNa if (gv) { index = gv->buffer_index; } else { - WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly."); + WARN_PRINT("Shader uses global parameter '" + E.key + "', but it was removed at some point. Material will not display correctly."); } uint32_t offset = p_uniform_offsets[E.value.order]; @@ -1070,7 +1070,7 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name); if (v) { if (v->buffer_index >= 0) { - WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); + WARN_PRINT("Shader uses global parameter texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); } else { HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name); @@ -1085,7 +1085,7 @@ void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Va } } else { - WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); + WARN_PRINT("Shader uses global parameter texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); } } else { HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name); @@ -1652,7 +1652,7 @@ int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) { return -1; } -void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value) { +void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: { GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index]; @@ -1945,7 +1945,7 @@ void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, } } -void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) { +void MaterialStorage::global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) { ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name)); GlobalShaderUniforms::Variable gv; gv.type = p_type; @@ -1983,7 +1983,7 @@ void MaterialStorage::global_shader_uniform_add(const StringName &p_name, RS::Gl global_shader_uniforms.variables[p_name] = gv; } -void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) { +void MaterialStorage::global_shader_parameter_remove(const StringName &p_name) { if (!global_shader_uniforms.variables.has(p_name)) { return; } @@ -1999,7 +1999,7 @@ void MaterialStorage::global_shader_uniform_remove(const StringName &p_name) { global_shader_uniforms.variables.erase(p_name); } -Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const { +Vector<StringName> MaterialStorage::global_shader_parameter_get_list() const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance."); } @@ -2012,7 +2012,7 @@ Vector<StringName> MaterialStorage::global_shader_uniform_get_list() const { return names; } -void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const Variant &p_value) { +void MaterialStorage::global_shader_parameter_set(const StringName &p_name, const Variant &p_value) { ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name)); GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name]; gv.value = p_value; @@ -2033,7 +2033,7 @@ void MaterialStorage::global_shader_uniform_set(const StringName &p_name, const } } -void MaterialStorage::global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) { +void MaterialStorage::global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) { if (!global_shader_uniforms.variables.has(p_name)) { return; //variable may not exist } @@ -2064,7 +2064,7 @@ void MaterialStorage::global_shader_uniform_set_override(const StringName &p_nam } } -Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) const { +Variant MaterialStorage::global_shader_parameter_get(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance."); } @@ -2076,7 +2076,7 @@ Variant MaterialStorage::global_shader_uniform_get(const StringName &p_name) con return global_shader_uniforms.variables[p_name].value; } -RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_internal(const StringName &p_name) const { +RS::GlobalShaderParameterType MaterialStorage::global_shader_parameter_get_type_internal(const StringName &p_name) const { if (!global_shader_uniforms.variables.has(p_name)) { return RS::GLOBAL_VAR_TYPE_MAX; } @@ -2084,15 +2084,15 @@ RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type_inte return global_shader_uniforms.variables[p_name].type; } -RS::GlobalShaderUniformType MaterialStorage::global_shader_uniform_get_type(const StringName &p_name) const { +RS::GlobalShaderParameterType MaterialStorage::global_shader_parameter_get_type(const StringName &p_name) const { if (!Engine::get_singleton()->is_editor_hint()) { ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance."); } - return global_shader_uniform_get_type_internal(p_name); + return global_shader_parameter_get_type_internal(p_name); } -void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) { +void MaterialStorage::global_shader_parameters_load_settings(bool p_load_textures) { List<PropertyInfo> settings; ProjectSettings::get_singleton()->get_property_list(&settings); @@ -2137,11 +2137,11 @@ void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) "samplerCube", }; - RS::GlobalShaderUniformType gvtype = RS::GLOBAL_VAR_TYPE_MAX; + RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX; for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) { if (global_var_type_names[i] == type) { - gvtype = RS::GlobalShaderUniformType(i); + gvtype = RS::GlobalShaderParameterType(i); break; } } @@ -2165,15 +2165,15 @@ void MaterialStorage::global_shader_uniforms_load_settings(bool p_load_textures) if (global_shader_uniforms.variables.has(name)) { //has it, update it - global_shader_uniform_set(name, value); + global_shader_parameter_set(name, value); } else { - global_shader_uniform_add(name, gvtype, value); + global_shader_parameter_add(name, gvtype, value); } } } } -void MaterialStorage::global_shader_uniforms_clear() { +void MaterialStorage::global_shader_parameters_clear() { global_shader_uniforms.variables.clear(); //not right but for now enough } @@ -2181,7 +2181,7 @@ RID MaterialStorage::global_shader_uniforms_get_storage_buffer() const { return global_shader_uniforms.buffer; } -int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance) { +int32_t MaterialStorage::global_shader_parameters_instance_allocate(RID p_instance) { ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1); int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES); global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway @@ -2190,7 +2190,7 @@ int32_t MaterialStorage::global_shader_uniforms_instance_allocate(RID p_instance return pos; } -void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) { +void MaterialStorage::global_shader_parameters_instance_free(RID p_instance) { ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance)); int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance]; if (pos >= 0) { @@ -2199,7 +2199,7 @@ void MaterialStorage::global_shader_uniforms_instance_free(RID p_instance) { global_shader_uniforms.instance_buffer_pos.erase(p_instance); } -void MaterialStorage::global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) { +void MaterialStorage::global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value) { if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) { return; //just not allocated, ignore } @@ -2384,7 +2384,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { if (shader->data) { for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) { for (const KeyValue<int, RID> &E2 : E.value) { - shader->data->set_default_texture_param(E.key, E2.value, E2.key); + shader->data->set_default_texture_parameter(E.key, E2.value, E2.key); } } } @@ -2418,7 +2418,7 @@ String MaterialStorage::shader_get_code(RID p_shader) const { return shader->code; } -void MaterialStorage::shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const { +void MaterialStorage::get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); if (shader->data) { @@ -2426,7 +2426,7 @@ void MaterialStorage::shader_get_shader_uniform_list(RID p_shader, List<Property } } -void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { +void MaterialStorage::shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND(!shader); @@ -2445,7 +2445,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin } } if (shader->data) { - shader->data->set_default_texture_param(p_name, p_texture, p_index); + shader->data->set_default_texture_parameter(p_name, p_texture, p_index); } for (Material *E : shader->owners) { Material *material = E; @@ -2453,7 +2453,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin } } -RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const { +RID MaterialStorage::shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, RID()); if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) { @@ -2463,7 +2463,7 @@ RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const String return RID(); } -Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const { +Variant MaterialStorage::shader_get_parameter_default(RID p_shader, const StringName &p_param) const { Shader *shader = shader_owner.get_or_null(p_shader); ERR_FAIL_COND_V(!shader, Variant()); if (shader->data) { @@ -2616,7 +2616,7 @@ void MaterialStorage::material_set_param(RID p_material, const StringName &p_par } if (material->shader && material->shader->data) { //shader is valid - bool is_texture = material->shader->data->is_param_texture(p_param); + bool is_texture = material->shader->data->is_parameter_texture(p_param); _material_queue_update(material, !is_texture, is_texture); } else { _material_queue_update(material, true, true); @@ -2684,14 +2684,14 @@ bool MaterialStorage::material_casts_shadows(RID p_material) { return true; //by default everything casts shadows } -void MaterialStorage::material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) { +void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) { Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); if (material->shader && material->shader->data) { material->shader->data->get_instance_param_list(r_parameters); if (material->next_pass.is_valid()) { - material_get_instance_shader_uniforms(material->next_pass, r_parameters); + material_get_instance_shader_parameters(material->next_pass, r_parameters); } } } diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index dbf7a92e23..db2e4cfa2a 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -56,11 +56,11 @@ public: struct ShaderData { virtual void set_code(const String &p_Code) = 0; virtual void set_path_hint(const String &p_hint) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0; + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) = 0; virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0; - virtual bool is_param_texture(const StringName &p_param) const = 0; + virtual bool is_parameter_texture(const StringName &p_param) const = 0; virtual bool is_animated() const = 0; virtual bool casts_shadows() const = 0; virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; @@ -119,7 +119,7 @@ private: struct Variable { HashSet<RID> texture_materials; // materials using this - RS::GlobalShaderUniformType type; + RS::GlobalShaderParameterType type; Variant value; Variant override; int32_t buffer_index; //for vectors @@ -171,7 +171,7 @@ private: } global_shader_uniforms; int32_t _global_shader_uniform_allocate(uint32_t p_elements); - void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderUniformType p_type, const Variant &p_value); + void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value); void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements); /* SHADER API */ @@ -332,22 +332,22 @@ public: void _update_global_shader_uniforms(); - virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) override; - virtual void global_shader_uniform_remove(const StringName &p_name) override; - virtual Vector<StringName> global_shader_uniform_get_list() const override; + virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) override; + virtual void global_shader_parameter_remove(const StringName &p_name) override; + virtual Vector<StringName> global_shader_parameter_get_list() const override; - virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) override; - virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) override; - virtual Variant global_shader_uniform_get(const StringName &p_name) const override; - virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const override; - RS::GlobalShaderUniformType global_shader_uniform_get_type_internal(const StringName &p_name) const; + virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) override; + virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) override; + virtual Variant global_shader_parameter_get(const StringName &p_name) const override; + virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const override; + RS::GlobalShaderParameterType global_shader_parameter_get_type_internal(const StringName &p_name) const; - virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) override; - virtual void global_shader_uniforms_clear() override; + virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override; + virtual void global_shader_parameters_clear() override; - virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) override; - virtual void global_shader_uniforms_instance_free(RID p_instance) override; - virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) override; + virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override; + virtual void global_shader_parameters_instance_free(RID p_instance) override; + virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value) override; RID global_shader_uniforms_get_storage_buffer() const; @@ -362,11 +362,11 @@ public: virtual void shader_set_code(RID p_shader, const String &p_code) override; virtual void shader_set_path_hint(RID p_shader, const String &p_path) override; virtual String shader_get_code(RID p_shader) const override; - virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; + virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const override; - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override; - virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override; + virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override; + virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override; + virtual Variant shader_get_parameter_default(RID p_shader, const StringName &p_param) const override; void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override; @@ -394,7 +394,7 @@ public: virtual bool material_is_animated(RID p_material) override; virtual bool material_casts_shadows(RID p_material) override; - virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) override; + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override; virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override; diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 49d7198ec2..1827b73507 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "mesh_storage.h" +#include "../../rendering_server_globals.h" using namespace RendererRD; @@ -425,7 +426,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) } for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { const AABB &bone = p_surface.bone_aabbs[i]; - if (!bone.has_no_volume()) { + if (bone.has_volume()) { mesh->bone_aabbs.write[i].merge_with(bone); } } @@ -1211,7 +1212,13 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS:: if (multimesh->data_cache_dirty_regions) { memdelete_arr(multimesh->data_cache_dirty_regions); multimesh->data_cache_dirty_regions = nullptr; - multimesh->data_cache_used_dirty_regions = 0; + multimesh->data_cache_dirty_region_count = 0; + } + + if (multimesh->previous_data_cache_dirty_regions) { + memdelete_arr(multimesh->previous_data_cache_dirty_regions); + multimesh->previous_data_cache_dirty_regions = nullptr; + multimesh->previous_data_cache_dirty_region_count = 0; } multimesh->instances = p_instances; @@ -1228,14 +1235,67 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS:: multimesh->aabb = AABB(); multimesh->aabb_dirty = false; multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); + multimesh->motion_vectors_current_offset = 0; + multimesh->motion_vectors_previous_offset = 0; + multimesh->motion_vectors_last_change = -1; if (multimesh->instances) { - multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); + uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float); + if (multimesh->motion_vectors_enabled) { + buffer_size *= 2; + } + multimesh->buffer = RD::get_singleton()->storage_buffer_create(buffer_size); } multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH); } +bool MeshStorage::_multimesh_enable_motion_vectors(RID p_multimesh) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND_V(!multimesh, false); + + if (multimesh->motion_vectors_enabled) { + return false; + } + + multimesh->motion_vectors_enabled = true; + + multimesh->motion_vectors_current_offset = 0; + multimesh->motion_vectors_previous_offset = 0; + multimesh->motion_vectors_last_change = -1; + + if (!multimesh->data_cache.is_empty()) { + multimesh->data_cache.append_array(multimesh->data_cache); + } + + if (multimesh->buffer_set) { + RD::get_singleton()->barrier(); + Vector<uint8_t> buffer_data = RD::get_singleton()->buffer_get_data(multimesh->buffer); + if (!multimesh->data_cache.is_empty()) { + memcpy(buffer_data.ptrw(), multimesh->data_cache.ptr(), buffer_data.size()); + } + + RD::get_singleton()->free(multimesh->buffer); + uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float) * 2; + multimesh->buffer = RD::get_singleton()->storage_buffer_create(buffer_size); + RD::get_singleton()->buffer_update(multimesh->buffer, 0, buffer_data.size(), buffer_data.ptr(), RD::BARRIER_MASK_NO_BARRIER); + RD::get_singleton()->buffer_update(multimesh->buffer, buffer_data.size(), buffer_data.size(), buffer_data.ptr()); + multimesh->uniform_set_3d = RID(); // Cleared by dependency + return true; + } + return false; // Update the transforms uniform set cache +} + +void MeshStorage::_multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset) { + MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); + ERR_FAIL_COND(!multimesh); + r_current_offset = multimesh->motion_vectors_current_offset; + if (RSG::rasterizer->get_frame_number() - multimesh->motion_vectors_last_change >= 2) { + multimesh->motion_vectors_previous_offset = multimesh->motion_vectors_current_offset; + } + r_prev_offset = multimesh->motion_vectors_previous_offset; +} + int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); ERR_FAIL_COND_V(!multimesh, 0); @@ -1261,7 +1321,7 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { //need to re-create AABB unfortunately, calling this has a penalty if (multimesh->buffer_set) { Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - const uint8_t *r = buffer.ptr(); + const uint8_t *r = buffer.ptr() + multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float); const float *data = reinterpret_cast<const float *>(r); _multimesh_re_create_aabb(multimesh, data, multimesh->instances); } @@ -1276,10 +1336,14 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { if (multimesh->data_cache.size() > 0) { return; //already local } - ERR_FAIL_COND(multimesh->data_cache.size() > 0); + // this means that the user wants to load/save individual elements, // for this, the data must reside on CPU, so just copy it there. - multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); + uint32_t buffer_size = multimesh->instances * multimesh->stride_cache; + if (multimesh->motion_vectors_enabled) { + buffer_size *= 2; + } + multimesh->data_cache.resize(buffer_size); { float *w = multimesh->data_cache.ptrw(); @@ -1290,15 +1354,48 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const { memcpy(w, r, buffer.size()); } } else { - memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float)); + memset(w, 0, buffer_size * sizeof(float)); } } uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; + memset(multimesh->data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool)); + multimesh->data_cache_dirty_region_count = 0; + + multimesh->previous_data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); + memset(multimesh->previous_data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool)); + multimesh->previous_data_cache_dirty_region_count = 0; +} + +void MeshStorage::_multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh) { + ERR_FAIL_COND(multimesh->data_cache.is_empty()); + + if (!multimesh->motion_vectors_enabled) { + return; + } + + uint32_t frame = RSG::rasterizer->get_frame_number(); + if (multimesh->motion_vectors_last_change != frame) { + multimesh->motion_vectors_previous_offset = multimesh->motion_vectors_current_offset; + multimesh->motion_vectors_current_offset = multimesh->instances - multimesh->motion_vectors_current_offset; + multimesh->motion_vectors_last_change = frame; + + if (multimesh->previous_data_cache_dirty_region_count > 0) { + uint8_t *data = (uint8_t *)multimesh->data_cache.ptrw(); + uint32_t current_ofs = multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float); + uint32_t previous_ofs = multimesh->motion_vectors_previous_offset * multimesh->stride_cache * sizeof(float); + uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); + uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); + for (uint32_t i = 0; i < visible_region_count; i++) { + if (multimesh->previous_data_cache_dirty_regions[i]) { + uint32_t offset = i * region_size; + memcpy(data + current_ofs + offset, data + previous_ofs + offset, MIN(region_size, size - offset)); + } + } + } } - multimesh->data_cache_used_dirty_regions = 0; } void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { @@ -1309,7 +1406,7 @@ void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool #endif if (!multimesh->data_cache_dirty_regions[region_index]) { multimesh->data_cache_dirty_regions[region_index] = true; - multimesh->data_cache_used_dirty_regions++; + multimesh->data_cache_dirty_region_count++; } if (p_aabb) { @@ -1330,7 +1427,7 @@ void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, b for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { if (!multimesh->data_cache_dirty_regions[i]) { multimesh->data_cache_dirty_regions[i] = true; - multimesh->data_cache_used_dirty_regions++; + multimesh->data_cache_dirty_region_count++; } } } @@ -1395,11 +1492,12 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D); _multimesh_make_local(multimesh); + _multimesh_update_motion_vectors_data_cache(multimesh); { float *w = multimesh->data_cache.ptrw(); - float *dataptr = w + p_index * multimesh->stride_cache; + float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache; dataptr[0] = p_transform.basis.rows[0][0]; dataptr[1] = p_transform.basis.rows[0][1]; @@ -1425,11 +1523,12 @@ void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_ind ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D); _multimesh_make_local(multimesh); + _multimesh_update_motion_vectors_data_cache(multimesh); { float *w = multimesh->data_cache.ptrw(); - float *dataptr = w + p_index * multimesh->stride_cache; + float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache; dataptr[0] = p_transform.columns[0][0]; dataptr[1] = p_transform.columns[1][0]; @@ -1451,11 +1550,12 @@ void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, con ERR_FAIL_COND(!multimesh->uses_colors); _multimesh_make_local(multimesh); + _multimesh_update_motion_vectors_data_cache(multimesh); { float *w = multimesh->data_cache.ptrw(); - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->color_offset_cache; dataptr[0] = p_color.r; dataptr[1] = p_color.g; @@ -1473,11 +1573,12 @@ void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_inde ERR_FAIL_COND(!multimesh->uses_custom_data); _multimesh_make_local(multimesh); + _multimesh_update_motion_vectors_data_cache(multimesh); { float *w = multimesh->data_cache.ptrw(); - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->custom_data_offset_cache; dataptr[0] = p_color.r; dataptr[1] = p_color.g; @@ -1514,7 +1615,7 @@ Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p { const float *r = multimesh->data_cache.ptr(); - const float *dataptr = r + p_index * multimesh->stride_cache; + const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache; t.basis.rows[0][0] = dataptr[0]; t.basis.rows[0][1] = dataptr[1]; @@ -1545,7 +1646,7 @@ Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, in { const float *r = multimesh->data_cache.ptr(); - const float *dataptr = r + p_index * multimesh->stride_cache; + const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache; t.columns[0][0] = dataptr[0]; t.columns[1][0] = dataptr[1]; @@ -1570,7 +1671,7 @@ Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) co { const float *r = multimesh->data_cache.ptr(); - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->color_offset_cache; c.r = dataptr[0]; c.g = dataptr[1]; @@ -1593,7 +1694,7 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind { const float *r = multimesh->data_cache.ptr(); - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->custom_data_offset_cache; c.r = dataptr[0]; c.g = dataptr[1]; @@ -1609,25 +1710,26 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b ERR_FAIL_COND(!multimesh); ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); + if (multimesh->motion_vectors_enabled) { + uint32_t frame = RSG::rasterizer->get_frame_number(); + + if (multimesh->motion_vectors_last_change != frame) { + multimesh->motion_vectors_previous_offset = multimesh->motion_vectors_current_offset; + multimesh->motion_vectors_current_offset = multimesh->instances - multimesh->motion_vectors_current_offset; + multimesh->motion_vectors_last_change = frame; + } + } + { const float *r = p_buffer.ptr(); - RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r); + RD::get_singleton()->buffer_update(multimesh->buffer, multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float), p_buffer.size() * sizeof(float), r); multimesh->buffer_set = true; } if (multimesh->data_cache.size()) { - //if we have a data cache, just update it - multimesh->data_cache = p_buffer; - { - //clear dirty since nothing will be dirty anymore - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - multimesh->data_cache_used_dirty_regions = 0; - } - - _multimesh_mark_all_dirty(multimesh, false, true); //update AABB + float *cache_data = multimesh->data_cache.ptrw(); + memcpy(cache_data + (multimesh->motion_vectors_current_offset * multimesh->stride_cache), p_buffer.ptr(), p_buffer.size() * sizeof(float)); + _multimesh_mark_all_dirty(multimesh, true, true); //update AABB } else if (multimesh->mesh.is_valid()) { //if we have a mesh set, we need to re-generate the AABB from the new data const float *data = p_buffer.ptr(); @@ -1642,20 +1744,19 @@ Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const { ERR_FAIL_COND_V(!multimesh, Vector<float>()); if (multimesh->buffer.is_null()) { return Vector<float>(); - } else if (multimesh->data_cache.size()) { - return multimesh->data_cache; } else { - //get from memory - - Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); Vector<float> ret; ret.resize(multimesh->instances * multimesh->stride_cache); - { - float *w = ret.ptrw(); - const uint8_t *r = buffer.ptr(); - memcpy(w, r, buffer.size()); - } + float *w = ret.ptrw(); + if (multimesh->data_cache.size()) { + const uint8_t *r = (uint8_t *)multimesh->data_cache.ptr() + multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float); + memcpy(w, r, ret.size() * sizeof(float)); + } else { + Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + const uint8_t *r = buffer.ptr() + multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float); + memcpy(w, r, ret.size() * sizeof(float)); + } return ret; } } @@ -1698,36 +1799,38 @@ void MeshStorage::_update_dirty_multimeshes() { MultiMesh *multimesh = multimesh_dirty_list; if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists - const float *data = multimesh->data_cache.ptr(); uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + uint32_t buffer_offset = multimesh->motion_vectors_current_offset * multimesh->stride_cache; + const float *data = multimesh->data_cache.ptr() + buffer_offset; - if (multimesh->data_cache_used_dirty_regions) { + uint32_t total_dirty_regions = multimesh->data_cache_dirty_region_count + multimesh->previous_data_cache_dirty_region_count; + if (total_dirty_regions != 0) { uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); - - if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { + if (total_dirty_regions > 32 || total_dirty_regions > visible_region_count / 2) { //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much - RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data); + RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float), MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data); } else { //not that many regions? update them all for (uint32_t i = 0; i < visible_region_count; i++) { - if (multimesh->data_cache_dirty_regions[i]) { + if (multimesh->data_cache_dirty_regions[i] || multimesh->previous_data_cache_dirty_regions[i]) { uint32_t offset = i * region_size; uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float); uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i; - RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]); + RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float) + offset, MIN(region_size, size - offset), &data[region_start_index], RD::BARRIER_MASK_NO_BARRIER); } } + RD::get_singleton()->barrier(RD::BARRIER_MASK_NO_BARRIER, RD::BARRIER_MASK_ALL); } - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } + memcpy(multimesh->previous_data_cache_dirty_regions, multimesh->data_cache_dirty_regions, data_cache_dirty_region_count * sizeof(bool)); + memset(multimesh->data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool)); - multimesh->data_cache_used_dirty_regions = 0; + multimesh->previous_data_cache_dirty_region_count = multimesh->data_cache_dirty_region_count; + multimesh->data_cache_dirty_region_count = 0; } if (multimesh->aabb_dirty) { diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 5c0d019c15..622f3911c7 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -205,13 +205,19 @@ private: AABB aabb; bool aabb_dirty = false; bool buffer_set = false; + bool motion_vectors_enabled = false; + uint32_t motion_vectors_current_offset = 0; + uint32_t motion_vectors_previous_offset = 0; + uint64_t motion_vectors_last_change = -1; uint32_t stride_cache = 0; uint32_t color_offset_cache = 0; uint32_t custom_data_offset_cache = 0; Vector<float> data_cache; //used if individual setting is used bool *data_cache_dirty_regions = nullptr; - uint32_t data_cache_used_dirty_regions = 0; + uint32_t data_cache_dirty_region_count = 0; + bool *previous_data_cache_dirty_regions = nullptr; + uint32_t previous_data_cache_dirty_region_count = 0; RID buffer; //storage buffer RID uniform_set_3d; @@ -228,6 +234,7 @@ private: MultiMesh *multimesh_dirty_list = nullptr; _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; + _FORCE_INLINE_ void _multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh); _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); @@ -579,6 +586,8 @@ public: virtual AABB multimesh_get_aabb(RID p_multimesh) const override; void _update_dirty_multimeshes(); + bool _multimesh_enable_motion_vectors(RID p_multimesh); + void _multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset); _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh); diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 022b027644..424d2d3c7a 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -1586,7 +1586,7 @@ void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) { valid = true; } -void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) { +void ParticlesStorage::ParticlesShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) { if (!p_texture.is_valid()) { if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) { default_texture_params[p_name].erase(p_index); @@ -1655,7 +1655,7 @@ void ParticlesStorage::ParticlesShaderData::get_instance_param_list(List<Rendere } } -bool ParticlesStorage::ParticlesShaderData::is_param_texture(const StringName &p_param) const { +bool ParticlesStorage::ParticlesShaderData::is_parameter_texture(const StringName &p_param) const { if (!uniforms.has(p_param)) { return false; } diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 299fdc6ec8..af29f5022b 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -336,10 +336,10 @@ private: virtual void set_code(const String &p_Code); virtual void set_path_hint(const String &p_hint); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index); + virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index); virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const; virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_parameter_texture(const StringName &p_param) const; virtual bool is_animated() const; virtual bool casts_shadows() const; virtual Variant get_default_parameter(const StringName &p_parameter) const; diff --git a/servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h new file mode 100644 index 0000000000..d904012914 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h @@ -0,0 +1,48 @@ +/*************************************************************************/ +/* render_buffer_custom_data_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDER_BUFFER_CUSTOM_DATA_RD_H +#define RENDER_BUFFER_CUSTOM_DATA_RD_H + +#include "core/object/ref_counted.h" + +class RenderSceneBuffersRD; + +class RenderBufferCustomDataRD : public RefCounted { + GDCLASS(RenderBufferCustomDataRD, RefCounted); + +public: + virtual void configure(RenderSceneBuffersRD *p_render_buffers) = 0; + virtual void free_data() = 0; // called on cleanup + +private: +}; + +#endif // RENDER_BUFFER_CUSTOM_DATA_RD_H 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 new file mode 100644 index 0000000000..16fdbc07f5 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -0,0 +1,566 @@ +/*************************************************************************/ +/* render_scene_buffers_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "render_scene_buffers_rd.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" + +RenderSceneBuffersRD::RenderSceneBuffersRD() { +} + +RenderSceneBuffersRD::~RenderSceneBuffersRD() { + cleanup(); + + data_buffers.clear(); + + // need to investigate if we can remove these things. + if (cluster_builder) { + memdelete(cluster_builder); + } +} + +void RenderSceneBuffersRD::_bind_methods() { + ClassDB::bind_method(D_METHOD("has_texture", "context", "name"), &RenderSceneBuffersRD::has_texture); + // FIXME we can't pass RD::DataFormat, RD::TextureSamples and RD::TextureView in ClassDB, need to solve views differently... + // ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::create_texture); + // ClassDB::bind_method(D_METHOD("create_texture_from_format", "context", "name", "format", "view", "unique"), &RenderSceneBuffersRD::create_texture_from_format); + // ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture); + ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture); + // ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format); + ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice); + ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size); + ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context); +} + +void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) { + ERR_FAIL_COND(p_named_texture.texture.is_null()); + + uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps; + p_named_texture.sizes.resize(size); + + Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height); + + for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) { + for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) { + uint32_t index = layer * p_named_texture.format.mipmaps + mipmap; + + p_named_texture.sizes.ptrw()[index] = mipmap_size; + } + + mipmap_size.width = MAX(1, mipmap_size.width >> 1); + mipmap_size.height = MAX(1, mipmap_size.height >> 1); + } +} + +void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) { + if (p_named_texture.texture.is_valid()) { + RD::get_singleton()->free(p_named_texture.texture); + } + p_named_texture.texture = RID(); + p_named_texture.slices.clear(); // slices should be freed automatically as dependents... +} + +void RenderSceneBuffersRD::cleanup() { + // Free our data buffers (but don't destroy them) + for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) { + E.value->free_data(); + } + + // Clear our named textures + for (KeyValue<NTKey, NamedTexture> &E : named_textures) { + free_named_texture(E.value); + } + named_textures.clear(); + + // old stuff, to be re-evaluated... + + for (int i = 0; i < luminance.fb.size(); i++) { + RD::get_singleton()->free(luminance.fb[i]); + } + luminance.fb.clear(); + + for (int i = 0; i < luminance.reduce.size(); i++) { + RD::get_singleton()->free(luminance.reduce[i]); + } + luminance.reduce.clear(); + + if (luminance.current_fb.is_valid()) { + RD::get_singleton()->free(luminance.current_fb); + luminance.current_fb = RID(); + } + + if (luminance.current.is_valid()) { + RD::get_singleton()->free(luminance.current); + luminance.current = RID(); + } + + if (ss_effects.linear_depth.is_valid()) { + RD::get_singleton()->free(ss_effects.linear_depth); + ss_effects.linear_depth = RID(); + ss_effects.linear_depth_slices.clear(); + } + + if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) { + RD::get_singleton()->free(ss_effects.downsample_uniform_set); + ss_effects.downsample_uniform_set = RID(); + } + + sse->ssao_free(ss_effects.ssao); + sse->ssil_free(ss_effects.ssil); + sse->ssr_free(ssr); +} + +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) { + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + + ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view"); + + 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; + } + + if (p_use_taa) { + // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. + // This restores sharpness in still images to be roughly at the same level as without TAA, + // but moving scenes will still be blurrier. + p_texture_mipmap_bias -= 0.5; + } + + if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { + // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness. + // If both TAA and FXAA are enabled, combine their negative LOD biases together. + p_texture_mipmap_bias -= 0.25; + } + + material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias); + + // need to check if we really need to do this here.. + RendererSceneRenderRD::get_singleton()->update_uniform_sets(); + + render_target = p_render_target; + fsr_sharpness = p_fsr_sharpness; + msaa_3d = p_msaa_3d; + screen_space_aa = p_screen_space_aa; + use_taa = p_use_taa; + use_debanding = p_use_debanding; + view_count = p_view_count; + + /* may move this into our clustered renderer data object */ + if (can_be_storage) { + if (cluster_builder == nullptr) { + cluster_builder = memnew(ClusterBuilderRD); + } + cluster_builder->set_shared(RendererSceneRenderRD::get_singleton()->get_cluster_builder_shared()); + } + + // cleanout any old buffers we had. + cleanup(); + + // create our 3D render buffers + { + // Create our color buffer(s) + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer + + // our internal texture should have MSAA support if applicable + if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) { + usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } + + create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR, base_data_format, usage_bits); + } + + // Create our depth buffer + { + // TODO If we have depth buffer supplied externally, pick this up + + RD::DataFormat format; + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + + if (msaa_3d == RS::VIEWPORT_MSAA_DISABLED) { + format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + } else { + format = RD::DATA_FORMAT_R32_SFLOAT; + usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + } + + create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, format, usage_bits); + } + + // VRS (note, our vrs object will only be set if VRS is supported) + RID vrs_texture; + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target); + if (vrs && vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + vrs_texture = create_texture(RB_SCOPE_VRS, RB_TEXTURE, RD::DATA_FORMAT_R8_UINT, usage_bits, RD::TEXTURE_SAMPLES_1, vrs->get_vrs_texture_size(internal_size)); + } + + for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) { + E.value->configure(this); + } + + if (cluster_builder) { + RID sampler = RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + cluster_builder->setup(internal_size, max_cluster_elements, get_depth_texture(), sampler, get_internal_texture()); + } +} + +void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) { + fsr_sharpness = p_fsr_sharpness; +} + +void RenderSceneBuffersRD::set_texture_mipmap_bias(float p_texture_mipmap_bias) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias); +} + +void RenderSceneBuffersRD::set_use_debanding(bool p_use_debanding) { + use_debanding = p_use_debanding; +} + +// Named textures + +bool RenderSceneBuffersRD::has_texture(const StringName &p_context, const StringName &p_texture_name) const { + NTKey key(p_context, p_texture_name); + + return named_textures.has(key); +} + +RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) { + // Keep some useful data, we use default values when these are 0. + Size2i size = p_size == Size2i(0, 0) ? internal_size : p_size; + uint32_t layers = p_layers == 0 ? view_count : p_layers; + uint32_t mipmaps = p_mipmaps == 0 ? 1 : p_mipmaps; + + // Create our texture + RD::TextureFormat tf; + tf.format = p_data_format; + if (layers > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + } + + tf.width = size.x; + tf.height = size.y; + tf.depth = 1; + tf.array_layers = layers; + tf.mipmaps = mipmaps; + tf.usage_bits = p_usage_bits; + tf.samples = p_texture_samples; + + return create_texture_from_format(p_context, p_texture_name, tf, RD::TextureView(), p_unique); +} + +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. + + NTKey key(p_context, p_texture_name); + + // check if this is a known texture + if (named_textures.has(key)) { + return named_textures[key].texture; + } + + // Add a new entry.. + NamedTexture &named_texture = named_textures[key]; + named_texture.format = p_texture_format; + named_texture.is_unique = p_unique; + named_texture.texture = RD::get_singleton()->texture_create(p_texture_format, p_view); + + Array arr; + arr.push_back(p_context); + arr.push_back(p_texture_name); + RD::get_singleton()->set_resource_name(named_texture.texture, String("RenderBuffer {0}/{1}").format(arr)); + + update_sizes(named_texture); + + // The rest is lazy created.. + + return named_texture.texture; +} + +RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view) { + NTKey view_key(p_context, p_view_name); + + // check if this is a known texture + if (named_textures.has(view_key)) { + return named_textures[view_key].texture; + } + + NTKey key(p_context, p_texture_name); + + ERR_FAIL_COND_V(!named_textures.has(key), RID()); + + NamedTexture &named_texture = named_textures[key]; + NamedTexture &view_texture = named_textures[view_key]; + + view_texture.format = named_texture.format; + view_texture.is_unique = named_texture.is_unique; + + view_texture.texture = RD::get_singleton()->texture_create_shared(p_view, named_texture.texture); + + Array arr; + arr.push_back(p_context); + arr.push_back(p_view_name); + RD::get_singleton()->set_resource_name(view_texture.texture, String("RenderBuffer View {0}/{1}").format(arr)); + + update_sizes(named_texture); + + return view_texture.texture; +} + +RID RenderSceneBuffersRD::get_texture(const StringName &p_context, const StringName &p_texture_name) const { + NTKey key(p_context, p_texture_name); + + ERR_FAIL_COND_V(!named_textures.has(key), RID()); + + return named_textures[key].texture; +} + +const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringName &p_context, const StringName &p_texture_name) const { + NTKey key(p_context, p_texture_name); + + ERR_FAIL_COND_V(!named_textures.has(key), RD::TextureFormat()); + + return named_textures[key].format; +} + +RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) { + NTKey key(p_context, p_texture_name); + + // check if this is a known texture + ERR_FAIL_COND_V(!named_textures.has(key), RID()); + NamedTexture &named_texture = named_textures[key]; + ERR_FAIL_COND_V(named_texture.texture.is_null(), RID()); + + // check if we're in bounds + ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID()); + ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID()); + + // if we don't have multiple layers or mipmaps, we can just return our texture as is + if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) { + return named_texture.texture; + } + + // get our index and make sure we have enough entries in our slices vector + uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap; + while (named_texture.slices.size() <= int(index)) { + named_texture.slices.push_back(RID()); + } + + // create our slice if we don't have it already + if (named_texture.slices[index].is_null()) { + named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap); + + Array arr; + arr.push_back(p_context); + arr.push_back(p_texture_name); + arr.push_back(itos(p_layer)); + arr.push_back(itos(p_mipmap)); + RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr)); + } + + // and return our slice + return named_texture.slices[index]; +} + +Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) { + NTKey key(p_context, p_texture_name); + + // check if this is a known texture + ERR_FAIL_COND_V(!named_textures.has(key), Size2i()); + NamedTexture &named_texture = named_textures[key]; + ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i()); + + // check if we're in bounds + ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i()); + ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i()); + + // get our index + uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap; + + // and return our size + return named_texture.sizes[index]; +} + +void RenderSceneBuffersRD::clear_context(const StringName &p_context) { + Vector<NTKey> to_free; // free these + + // Find all entries for our context, we don't want to free them yet or our loop fails. + for (KeyValue<NTKey, NamedTexture> &E : named_textures) { + if (E.key.context == p_context) { + to_free.push_back(E.key); + } + } + + // Now free these and remove them from our textures + for (NTKey &key : to_free) { + free_named_texture(named_textures[key]); + named_textures.erase(key); + } +} + +// Allocate shared buffers +void RenderSceneBuffersRD::allocate_blur_textures() { + if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) { + // already allocated... + return; + } + + uint32_t mipmaps_required = Image::get_image_required_mipmaps(internal_size.x, internal_size.y, Image::FORMAT_RGBAH); + + uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + if (can_be_storage) { + usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT; + } else { + usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } + + create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, internal_size, view_count, mipmaps_required); + create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y >> 1), view_count, mipmaps_required - 1); + + // if !can_be_storage we need a half width version + if (!can_be_storage) { + create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y), 1, mipmaps_required); + } + + // TODO redo this: + if (!can_be_storage) { + // create 4 weight textures, 2 full size, 2 half size + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP + tf.width = internal_size.x; + tf.height = internal_size.y; + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; // Our DOF effect handles one eye per turn + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf.mipmaps = 1; + for (uint32_t i = 0; i < 4; i++) { + // associated blur texture + RID texture; + if (i == 1) { + texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0); + } else if (i == 2) { + texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0); + } else if (i == 3) { + texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1); + } + + // create weight texture + weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + // create frame buffer + Vector<RID> fb; + if (i != 0) { + fb.push_back(texture); + } + fb.push_back(weight_buffers[i].weight); + weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb); + + if (i == 1) { + // next 2 are half size + tf.width = MAX(1u, tf.width >> 1); + tf.height = MAX(1u, tf.height >> 1); + } + } + } +} + +// Data buffers + +bool RenderSceneBuffersRD::has_custom_data(const StringName &p_name) { + return data_buffers.has(p_name); +} + +void RenderSceneBuffersRD::set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data) { + if (p_data.is_valid()) { + data_buffers[p_name] = p_data; + } else if (has_custom_data(p_name)) { + data_buffers.erase(p_name); + } +} + +Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const StringName &p_name) const { + ERR_FAIL_COND_V(!data_buffers.has(p_name), Ref<RenderBufferCustomDataRD>()); + + Ref<RenderBufferCustomDataRD> ret = data_buffers[p_name]; + + return ret; +} + +// Velocity texture. + +void RenderSceneBuffersRD::ensure_velocity() { + if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) { + uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) { + uint32_t msaa_usage_bits = usage_bits | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + + const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { + RD::TEXTURE_SAMPLES_1, + RD::TEXTURE_SAMPLES_2, + RD::TEXTURE_SAMPLES_4, + RD::TEXTURE_SAMPLES_8, + }; + + RD::TextureSamples texture_samples = ts[msaa_3d]; + + create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, RD::DATA_FORMAT_R16G16_SFLOAT, msaa_usage_bits, texture_samples); + } + + create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits); + } +} + +RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) { + if (p_get_msaa) { + if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) { + return RID(); + } else { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA); + } + } else { + if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) { + return RID(); + } else { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY); + } + } +} 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 new file mode 100644 index 0000000000..adaf075f80 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -0,0 +1,256 @@ +/*************************************************************************/ +/* render_scene_buffers_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDER_SCENE_BUFFERS_RD_H +#define RENDER_SCENE_BUFFERS_RD_H + +#include "core/templates/hash_map.h" +#include "servers/rendering/renderer_rd/effects/vrs.h" +#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h" +#include "servers/rendering/renderer_scene.h" +#include "servers/rendering/rendering_device.h" +#include "servers/rendering/storage/render_scene_buffers.h" + +// These can be retired in due time +#include "servers/rendering/renderer_rd/cluster_builder_rd.h" +#include "servers/rendering/renderer_rd/effects/ss_effects.h" +#include "servers/rendering/renderer_rd/environment/fog.h" + +#define RB_SCOPE_BUFFERS SNAME("render_buffers") +#define RB_SCOPE_VRS SNAME("VRS") + +#define RB_TEXTURE SNAME("texture") +#define RB_TEX_COLOR SNAME("color") +#define RB_TEX_COLOR_MSAA SNAME("color_msaa") +#define RB_TEX_DEPTH SNAME("depth") +#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa") +#define RB_TEX_VELOCITY SNAME("velocity") +#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa") + +#define RB_TEX_BLUR_0 SNAME("blur_0") +#define RB_TEX_BLUR_1 SNAME("blur_1") +#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster! + +#define RB_TEX_BACK_DEPTH SNAME("back_depth") + +class RenderSceneBuffersRD : public RenderSceneBuffers { + GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers); + +private: + bool can_be_storage = true; + uint32_t max_cluster_elements = 512; + RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + RendererRD::SSEffects *sse = nullptr; + RendererRD::VRS *vrs = nullptr; + uint64_t auto_exposure_version = 1; + + // Our render target represents our final destination that we display on screen. + RID render_target; + Size2i target_size = Size2i(0, 0); + uint32_t view_count = 1; + + // 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); + float fsr_sharpness = 0.2f; + + // Aliassing settings + RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED; + RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + bool use_taa = false; + bool use_debanding = false; + + // Named Textures + + struct NTKey { + StringName context; + StringName buffer_name; + + bool operator==(const NTKey &p_val) const { + return (context == p_val.context) && (buffer_name == p_val.buffer_name); + } + + static uint32_t hash(const NTKey &p_val) { + // FIXME, properly hash two stringnames together + uint32_t h = p_val.context.hash(); + h = hash_murmur3_one_32(p_val.buffer_name.hash(), h); + return hash_fmix32(h); + } + + NTKey() {} + NTKey(const StringName p_context, const StringName p_texture_name) { + context = p_context; + buffer_name = p_texture_name; + } + }; + + struct NamedTexture { + // Cache the data used to create our texture + RD::TextureFormat format; + bool is_unique; // If marked as unique, we return it into our pool + + // Our texture objects, slices are lazy (i.e. only created when requested). + RID texture; + Vector<RID> slices; + Vector<Size2i> sizes; + }; + + mutable HashMap<NTKey, NamedTexture, NTKey> named_textures; + void update_sizes(NamedTexture &p_named_texture); + void free_named_texture(NamedTexture &p_named_texture); + + // Data buffers + mutable HashMap<StringName, Ref<RenderBufferCustomDataRD>> data_buffers; + +protected: + static void _bind_methods(); + +public: + RenderSceneBuffersRD(); + virtual ~RenderSceneBuffersRD(); + + // info from our renderer + void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; } + void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; } + void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; } + RD::DataFormat get_base_data_format() const { return base_data_format; } + void set_sseffects(RendererRD::SSEffects *p_ss_effects) { sse = p_ss_effects; } + 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 set_fsr_sharpness(float p_fsr_sharpness) override; + virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override; + virtual void set_use_debanding(bool p_use_debanding) override; + + // Named Textures + + bool has_texture(const StringName &p_context, const StringName &p_texture_name) const; + RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true); + RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true); + RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView()); + RID get_texture(const StringName &p_context, const StringName &p_texture_name) const; + const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const; + RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap); + Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap); + + void clear_context(const StringName &p_context); + + // Allocate shared buffers + void allocate_blur_textures(); + + // Custom data + bool has_custom_data(const StringName &p_name); + void set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data); + Ref<RenderBufferCustomDataRD> get_custom_data(const StringName &p_name) const; + + // Getters + + _FORCE_INLINE_ RID get_render_target() const { return render_target; } + _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_ 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; } + _FORCE_INLINE_ bool get_use_taa() const { return use_taa; } + _FORCE_INLINE_ bool get_use_debanding() const { return use_debanding; } + + uint64_t get_auto_exposure_version() const { return auto_exposure_version; } + void set_auto_exposure_version(const uint64_t p_auto_exposure_version) { auto_exposure_version = p_auto_exposure_version; } + + // For our internal textures we provide some easy access methods. + + _FORCE_INLINE_ RID get_internal_texture() const { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR); + } + _FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0); + } + + _FORCE_INLINE_ RID get_depth_texture() const { + return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH); + } + _FORCE_INLINE_ RID get_depth_texture(const uint32_t p_layer) { + return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0); + } + + // back buffer (color) + RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here. + + // Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too. + + void ensure_velocity(); + bool has_velocity_buffer(bool p_has_msaa) { return has_texture(RB_SCOPE_BUFFERS, p_has_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY); } + RID get_velocity_buffer(bool p_get_msaa); + RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) { return get_texture_slice(RB_SCOPE_BUFFERS, p_get_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY, p_layer, 0); } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Everything after this needs to be re-evaluated, this is all old implementation + + ClusterBuilderRD *cluster_builder = nullptr; + + struct WeightBuffers { + RID weight; + RID fb; // FB with both texture and weight writing into one level lower + }; + + // 2 full size, 2 half size + WeightBuffers weight_buffers[4]; // Only used in raster + + struct Luminance { + Vector<RID> reduce; + RID current; + + // used only on mobile renderer + Vector<RID> fb; + RID current_fb; + } luminance; + + struct SSEffects { + RID linear_depth; + Vector<RID> linear_depth_slices; + + RID downsample_uniform_set; + + Projection last_frame_projection; + Transform3D last_frame_transform; + + RendererRD::SSEffects::SSAORenderBuffers ssao; + RendererRD::SSEffects::SSILRenderBuffers ssil; + } ss_effects; + + RendererRD::SSEffects::SSRRenderBuffers ssr; + + RID get_ao_texture() const { return ss_effects.ssao.ao_final; } + RID get_ssil_texture() const { return ss_effects.ssil.ssil_final; } +}; + +#endif // RENDER_SCENE_BUFFERS_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp new file mode 100644 index 0000000000..f925f87cbe --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -0,0 +1,246 @@ +/*************************************************************************/ +/* render_scene_data_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "render_scene_data_rd.h" +#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/light_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" +#include "servers/rendering/rendering_server_default.h" + +RID RenderSceneDataRD::create_uniform_buffer() { + return RD::get_singleton()->uniform_buffer_create(sizeof(UBODATA)); +} + +void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers) { + RendererSceneRenderRD *render_scene_render = RendererSceneRenderRD::get_singleton(); + + UBODATA ubo_data; + memset(&ubo_data, 0, sizeof(UBODATA)); + + // just for easy access.. + UBO &ubo = ubo_data.ubo; + UBO &prev_ubo = ubo_data.prev_ubo; + + Projection correction; + correction.set_depth_correction(p_flip_y); + correction.add_jitter_offset(taa_jitter); + Projection projection = correction * cam_projection; + + //store camera into ubo + RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix); + RendererRD::MaterialStorage::store_camera(projection.inverse(), ubo.inv_projection_matrix); + RendererRD::MaterialStorage::store_transform(cam_transform, ubo.inv_view_matrix); + RendererRD::MaterialStorage::store_transform(cam_transform.affine_inverse(), ubo.view_matrix); + + for (uint32_t v = 0; v < view_count; v++) { + projection = correction * view_projection[v]; + RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix_view[v]); + RendererRD::MaterialStorage::store_camera(projection.inverse(), ubo.inv_projection_matrix_view[v]); + + ubo.eye_offset[v][0] = view_eye_offset[v].x; + ubo.eye_offset[v][1] = view_eye_offset[v].y; + ubo.eye_offset[v][2] = view_eye_offset[v].z; + ubo.eye_offset[v][3] = 0.0; + } + + ubo.taa_jitter[0] = taa_jitter.x; + ubo.taa_jitter[1] = taa_jitter.y; + + ubo.z_far = z_far; + ubo.z_near = z_near; + + ubo.pancake_shadows = p_pancake_shadows; + + RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_penumbra_shadow_kernel_get(), ubo.directional_penumbra_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_soft_shadow_kernel_get(), ubo.directional_soft_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->penumbra_shadow_kernel_get(), ubo.penumbra_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->soft_shadow_kernel_get(), ubo.soft_shadow_kernel); + + ubo.viewport_size[0] = p_screen_size.x; + ubo.viewport_size[1] = p_screen_size.y; + + Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size); + ubo.screen_pixel_size[0] = screen_pixel_size.x; + ubo.screen_pixel_size[1] = screen_pixel_size.y; + + ubo.shadow_atlas_pixel_size[0] = shadow_atlas_pixel_size.x; + ubo.shadow_atlas_pixel_size[1] = shadow_atlas_pixel_size.y; + + ubo.directional_shadow_pixel_size[0] = directional_shadow_pixel_size.x; + ubo.directional_shadow_pixel_size[1] = directional_shadow_pixel_size.y; + + ubo.time = time; + + ubo.directional_light_count = directional_light_count; + ubo.dual_paraboloid_side = dual_paraboloid_side; + ubo.opaque_prepass_threshold = opaque_prepass_threshold; + ubo.material_uv2_mode = material_uv2_mode; + + ubo.fog_enabled = false; + + if (p_debug_mode == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { + ubo.use_ambient_light = true; + ubo.ambient_light_color_energy[0] = 1; + ubo.ambient_light_color_energy[1] = 1; + ubo.ambient_light_color_energy[2] = 1; + ubo.ambient_light_color_energy[3] = 1.0; + ubo.use_ambient_cubemap = false; + ubo.use_reflection_cubemap = false; + } else if (p_env.is_valid()) { + RS::EnvironmentBG env_bg = render_scene_render->environment_get_background(p_env); + RS::EnvironmentAmbientSource ambient_src = render_scene_render->environment_get_ambient_source(p_env); + + float bg_energy_multiplier = render_scene_render->environment_get_bg_energy_multiplier(p_env); + + ubo.ambient_light_color_energy[3] = bg_energy_multiplier; + + ubo.ambient_color_sky_mix = render_scene_render->environment_get_ambient_sky_contribution(p_env); + + //ambient + if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { + Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : render_scene_render->environment_get_bg_color(p_env); + color = color.srgb_to_linear(); + + ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier; + ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier; + ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier; + ubo.use_ambient_light = true; + ubo.use_ambient_cubemap = false; + } else { + float energy = render_scene_render->environment_get_ambient_light_energy(p_env); + Color color = render_scene_render->environment_get_ambient_light(p_env); + color = color.srgb_to_linear(); + ubo.ambient_light_color_energy[0] = color.r * energy; + ubo.ambient_light_color_energy[1] = color.g * energy; + ubo.ambient_light_color_energy[2] = color.b * energy; + + Basis sky_transform = render_scene_render->environment_get_sky_orientation(p_env); + sky_transform = sky_transform.inverse() * cam_transform.basis; + RendererRD::MaterialStorage::store_transform_3x3(sky_transform, ubo.radiance_inverse_xform); + + ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; + ubo.use_ambient_light = ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; + } + + //specular + RS::EnvironmentReflectionSource ref_src = render_scene_render->environment_get_reflection_source(p_env); + if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) { + ubo.use_reflection_cubemap = true; + } else { + ubo.use_reflection_cubemap = false; + } + + ubo.fog_enabled = render_scene_render->environment_get_fog_enabled(p_env); + ubo.fog_density = render_scene_render->environment_get_fog_density(p_env); + ubo.fog_height = render_scene_render->environment_get_fog_height(p_env); + ubo.fog_height_density = render_scene_render->environment_get_fog_height_density(p_env); + ubo.fog_aerial_perspective = render_scene_render->environment_get_fog_aerial_perspective(p_env); + + Color fog_color = render_scene_render->environment_get_fog_light_color(p_env).srgb_to_linear(); + float fog_energy = render_scene_render->environment_get_fog_light_energy(p_env); + + ubo.fog_light_color[0] = fog_color.r * fog_energy; + ubo.fog_light_color[1] = fog_color.g * fog_energy; + ubo.fog_light_color[2] = fog_color.b * fog_energy; + + ubo.fog_sun_scatter = render_scene_render->environment_get_fog_sun_scatter(p_env); + } else { + if (p_reflection_probe_instance.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(p_reflection_probe_instance)) { + ubo.use_ambient_light = false; + } else { + ubo.use_ambient_light = true; + Color clear_color = p_default_bg_color; + clear_color = clear_color.srgb_to_linear(); + ubo.ambient_light_color_energy[0] = clear_color.r; + ubo.ambient_light_color_energy[1] = clear_color.g; + ubo.ambient_light_color_energy[2] = clear_color.b; + ubo.ambient_light_color_energy[3] = 1.0; + } + + ubo.use_ambient_cubemap = false; + ubo.use_reflection_cubemap = false; + } + + if (p_camera_attributes.is_valid()) { + ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes); + ubo.IBL_exposure_normalization = 1.0; + if (p_env.is_valid()) { + RID sky_rid = render_scene_render->environment_get_sky(p_env); + if (sky_rid.is_valid()) { + float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes) * render_scene_render->environment_get_bg_intensity(p_env) / p_luminance_multiplier; + ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, render_scene_render->get_sky()->sky_get_baked_exposure(sky_rid)); + } + } + } else if (emissive_exposure_normalization > 0.0) { + // This branch is triggered when using render_material(). + // Emissive is set outside the function. + ubo.emissive_exposure_normalization = emissive_exposure_normalization; + // IBL isn't used don't set it. + } else { + ubo.emissive_exposure_normalization = 1.0; + ubo.IBL_exposure_normalization = 1.0; + } + + ubo.roughness_limiter_enabled = p_opaque_render_buffers && render_scene_render->screen_space_roughness_limiter_is_active(); + ubo.roughness_limiter_amount = render_scene_render->screen_space_roughness_limiter_get_amount(); + ubo.roughness_limiter_limit = render_scene_render->screen_space_roughness_limiter_get_limit(); + + if (calculate_motion_vectors) { + // Q : Should we make a complete copy or should we define a separate UBO with just the components we need? + memcpy(&prev_ubo, &ubo, sizeof(UBO)); + + Projection prev_correction; + prev_correction.set_depth_correction(true); + prev_correction.add_jitter_offset(prev_taa_jitter); + Projection prev_projection = prev_correction * prev_cam_projection; + + //store camera into ubo + RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix); + RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), prev_ubo.inv_projection_matrix); + RendererRD::MaterialStorage::store_transform(prev_cam_transform, prev_ubo.inv_view_matrix); + RendererRD::MaterialStorage::store_transform(prev_cam_transform.affine_inverse(), prev_ubo.view_matrix); + + for (uint32_t v = 0; v < view_count; v++) { + prev_projection = prev_correction * view_projection[v]; + RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix_view[v]); + RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), prev_ubo.inv_projection_matrix_view[v]); + } + prev_ubo.taa_jitter[0] = prev_taa_jitter.x; + prev_ubo.taa_jitter[1] = prev_taa_jitter.y; + prev_ubo.time -= time_step; + } + + uniform_buffer = p_uniform_buffer; + RD::get_singleton()->buffer_update(uniform_buffer, 0, sizeof(UBODATA), &ubo, RD::BARRIER_MASK_RASTER); +} + +RID RenderSceneDataRD::get_uniform_buffer() { + return uniform_buffer; +} diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h new file mode 100644 index 0000000000..c2dc7d5f4c --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -0,0 +1,157 @@ +/*************************************************************************/ +/* render_scene_data_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDER_SCENE_DATA_RD_H +#define RENDER_SCENE_DATA_RD_H + +#include "render_scene_buffers_rd.h" +#include "servers/rendering/renderer_scene_render.h" +#include "servers/rendering/rendering_device.h" + +// This is a container for data related to rendering a single frame of a viewport where we load this data into a UBO +// that can be used by the main scene shader but also by various effects. + +class RenderSceneDataRD { +public: + bool calculate_motion_vectors = false; + + Transform3D cam_transform; + Projection cam_projection; + Vector2 taa_jitter; + bool cam_orthogonal = false; + + // For stereo rendering + uint32_t view_count = 1; + Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; + Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + + Transform3D prev_cam_transform; + Projection prev_cam_projection; + Vector2 prev_taa_jitter; + Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + + float z_near = 0.0; + float z_far = 0.0; + + float lod_distance_multiplier = 0.0; + Plane lod_camera_plane; + float screen_mesh_lod_threshold = 0.0; + + uint32_t directional_light_count = 0; + float dual_paraboloid_side = 0.0; + float opaque_prepass_threshold = 0.0; + bool material_uv2_mode = false; + float emissive_exposure_normalization = 0.0; + + Size2 shadow_atlas_pixel_size; + Size2 directional_shadow_pixel_size; + + float time; + float time_step; + + RID create_uniform_buffer(); + void update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers); + RID get_uniform_buffer(); + +private: + RID uniform_buffer; // loaded into this uniform buffer (supplied externally) + + // This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code + struct UBO { + float projection_matrix[16]; + float inv_projection_matrix[16]; + float inv_view_matrix[16]; + float view_matrix[16]; + + float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; + float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; + float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4]; + + float viewport_size[2]; + float screen_pixel_size[2]; + + float directional_penumbra_shadow_kernel[128]; //32 vec4s + float directional_soft_shadow_kernel[128]; + float penumbra_shadow_kernel[128]; + float soft_shadow_kernel[128]; + + float radiance_inverse_xform[12]; + + float ambient_light_color_energy[4]; + + float ambient_color_sky_mix; + uint32_t use_ambient_light; + uint32_t use_ambient_cubemap; + uint32_t use_reflection_cubemap; + + float shadow_atlas_pixel_size[2]; + float directional_shadow_pixel_size[2]; + + uint32_t directional_light_count; + float dual_paraboloid_side; + float z_far; + float z_near; + + uint32_t roughness_limiter_enabled; + float roughness_limiter_amount; + float roughness_limiter_limit; + float opaque_prepass_threshold; + + // Fog + uint32_t fog_enabled; + float fog_density; + float fog_height; + float fog_height_density; + + float fog_light_color[3]; + float fog_sun_scatter; + + float fog_aerial_perspective; + float time; + float reflection_multiplier; + uint32_t material_uv2_mode; + + float taa_jitter[2]; + float emissive_exposure_normalization; // Needed to normalize emissive when using physical units. + float IBL_exposure_normalization; // Adjusts for baked exposure. + + uint32_t pancake_shadows; + uint32_t pad1; + uint32_t pad2; + uint32_t pad3; + }; + + struct UBODATA { + UBO ubo; + UBO prev_ubo; + }; +}; + +#endif // RENDER_SCENE_DATA_RD_H diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index ce19187071..b87b4d4a0f 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -2120,6 +2120,7 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) { if (rt->color.is_valid()) { RD::get_singleton()->free(rt->color); } + rt->color_slices.clear(); // these are automatically freed. if (rt->color_multisample.is_valid()) { RD::get_singleton()->free(rt->color_multisample); @@ -2174,6 +2175,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { } rd_color_attachment_format.samples = RD::TEXTURE_SAMPLES_1; rd_color_attachment_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + rd_color_attachment_format.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; // FIXME we need this only when FSR is enabled rd_color_attachment_format.shareable_formats.push_back(rt->color_format); rd_color_attachment_format.shareable_formats.push_back(rt->color_format_srgb); if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) { @@ -2392,6 +2394,24 @@ RID TextureStorage::render_target_get_rd_texture(RID p_render_target) { return rt->color; } +RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + if (rt->view_count == 1) { + return rt->color; + } else { + ERR_FAIL_UNSIGNED_INDEX_V(p_layer, rt->view_count, RID()); + if (rt->color_slices.size() == 0) { + for (uint32_t v = 0; v < rt->view_count; v++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->color, v, 0); + rt->color_slices.push_back(slice); + } + } + return rt->color_slices[p_layer]; + } +} + RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, RID()); diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index 25d355d878..a3acad30f3 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -254,6 +254,7 @@ private: uint32_t view_count; RID framebuffer; RID color; + Vector<RID> color_slices; RID color_multisample; // Needed when MSAA is enabled. RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; @@ -589,6 +590,7 @@ public: Size2 render_target_get_size(RID p_render_target); RID render_target_get_rd_framebuffer(RID p_render_target); RID render_target_get_rd_texture(RID p_render_target); + RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer); RID render_target_get_rd_backbuffer(RID p_render_target); RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target); diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp index fcef2f24bf..b80bcd514f 100644 --- a/servers/rendering/renderer_rd/storage_rd/utilities.cpp +++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp @@ -155,8 +155,8 @@ void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base); p_instance->update_dependency(dependency); } else if (GI::get_singleton()->owns_voxel_gi(p_base)) { - GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base); - p_instance->update_dependency(&gip->dependency); + Dependency *dependency = GI::get_singleton()->voxel_gi_get_dependency(p_base); + p_instance->update_dependency(dependency); } else if (LightStorage::get_singleton()->owns_lightmap(p_base)) { Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base); p_instance->update_dependency(dependency); diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/renderer_scene.h index ceb205a2f6..29c65fcffb 100644 --- a/servers/rendering/renderer_scene.h +++ b/servers/rendering/renderer_scene.h @@ -31,6 +31,7 @@ #ifndef RENDERER_SCENE_H #define RENDERER_SCENE_H +#include "servers/rendering/storage/render_scene_buffers.h" #include "servers/rendering_server.h" #include "servers/xr/xr_interface.h" @@ -100,10 +101,10 @@ public: virtual void instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) = 0; virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index) = 0; virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0; - virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0; - virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; - virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const = 0; - virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const = 0; + virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) = 0; + virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; + virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0; + virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0; virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0; @@ -154,7 +155,7 @@ public: virtual float environment_get_white(RID p_env) const = 0; // Fog - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) = 0; virtual bool environment_get_fog_enabled(RID p_env) const = 0; virtual Color environment_get_fog_light_color(RID p_env) const = 0; @@ -164,9 +165,10 @@ public: virtual float environment_get_fog_height(RID p_env) const = 0; virtual float environment_get_fog_height_density(RID p_env) const = 0; virtual float environment_get_fog_aerial_perspective(RID p_env) const = 0; + virtual float environment_get_fog_sky_affect(RID p_env) const = 0; // Volumetric Fog - virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0; + virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0; virtual bool environment_get_volumetric_fog_enabled(RID p_env) const = 0; virtual float environment_get_volumetric_fog_density(RID p_env) const = 0; @@ -177,6 +179,7 @@ public: virtual float environment_get_volumetric_fog_length(RID p_env) const = 0; virtual float environment_get_volumetric_fog_detail_spread(RID p_env) const = 0; virtual float environment_get_volumetric_fog_gi_inject(RID p_env) const = 0; + virtual float environment_get_volumetric_fog_sky_affect(RID p_env) const = 0; virtual bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const = 0; virtual float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const = 0; virtual float environment_get_volumetric_fog_ambient_inject(RID p_env) const = 0; @@ -287,26 +290,24 @@ public: /* Render Buffers */ - virtual RID render_buffers_create() = 0; - - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0; + virtual Ref<RenderSceneBuffers> render_buffers_create() = 0; virtual void gi_set_use_half_resolution(bool p_enable) = 0; virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; - virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0; + virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) = 0; virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0; virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0; - virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0; + virtual void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0; struct RenderInfo { int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {}; }; - virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0; + virtual void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0; virtual void update() = 0; virtual void render_probes() = 0; diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 5276322651..04dedc0646 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -1436,7 +1436,7 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l } } -void RendererSceneCull::instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value) { +void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value) { Instance *instance = instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); @@ -1454,12 +1454,12 @@ void RendererSceneCull::instance_geometry_set_shader_uniform(RID p_instance, con E->value.value = p_value; if (E->value.index >= 0 && instance->instance_allocated_shader_uniforms) { //update directly - RSG::material_storage->global_shader_uniforms_instance_update(p_instance, E->value.index, p_value); + RSG::material_storage->global_shader_parameters_instance_update(p_instance, E->value.index, p_value); } } } -Variant RendererSceneCull::instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const { +Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const { const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance); ERR_FAIL_COND_V(!instance, Variant()); @@ -1469,7 +1469,7 @@ Variant RendererSceneCull::instance_geometry_get_shader_uniform(RID p_instance, return Variant(); } -Variant RendererSceneCull::instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const { +Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const { const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance); ERR_FAIL_COND_V(!instance, Variant()); @@ -1479,7 +1479,7 @@ Variant RendererSceneCull::instance_geometry_get_shader_uniform_default_value(RI return Variant(); } -void RendererSceneCull::instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const { +void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const { const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance); ERR_FAIL_COND(!instance); @@ -1563,7 +1563,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) { } } - if (p_instance->aabb.has_no_surface()) { + if (!p_instance->aabb.has_surface()) { return; } @@ -2450,7 +2450,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons return animated_material_found; } -void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) { +void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) { #ifndef _3D_DISABLED Camera *camera = camera_owner.get_or_null(p_camera); @@ -2910,7 +2910,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul } } -void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) { +void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) { Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it Scenario *scenario = scenario_owner.get_or_null(p_scenario); @@ -3270,8 +3270,6 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) { render_sdfgi_data[i].instances.clear(); } - - // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0; } RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { @@ -3295,7 +3293,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) { return RID(); } -void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { +void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) { #ifndef _3D_DISABLED Scenario *scenario = scenario_owner.get_or_null(p_scenario); @@ -3383,7 +3381,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int RendererSceneRender::CameraData camera_data; camera_data.set_camera(xform, cm, false, false); - _render_scene(&camera_data, RID(), environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows); + Ref<RenderSceneBuffers> render_buffers; + _render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows); } else { //do roughness postprocess step until it believes it's done @@ -3677,7 +3676,7 @@ void RendererSceneCull::render_particle_colliders() { void RendererSceneCull::_update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) { List<RendererMaterialStorage::InstanceShaderParam> plist; - RSG::material_storage->material_get_instance_shader_uniforms(p_material, &plist); + RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist); for (const RendererMaterialStorage::InstanceShaderParam &E : plist) { StringName name = E.info.name; if (isparams.has(name)) { @@ -3883,17 +3882,17 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) { if (p_instance->instance_allocated_shader_uniforms != (p_instance->instance_shader_uniforms.size() > 0)) { p_instance->instance_allocated_shader_uniforms = (p_instance->instance_shader_uniforms.size() > 0); if (p_instance->instance_allocated_shader_uniforms) { - p_instance->instance_allocated_shader_uniforms_offset = RSG::material_storage->global_shader_uniforms_instance_allocate(p_instance->self); + p_instance->instance_allocated_shader_uniforms_offset = RSG::material_storage->global_shader_parameters_instance_allocate(p_instance->self); ERR_FAIL_NULL(geom->geometry_instance); geom->geometry_instance->set_instance_shader_uniforms_offset(p_instance->instance_allocated_shader_uniforms_offset); for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_uniforms) { if (E.value.value.get_type() != Variant::NIL) { - RSG::material_storage->global_shader_uniforms_instance_update(p_instance->self, E.value.index, E.value.value); + RSG::material_storage->global_shader_parameters_instance_update(p_instance->self, E.value.index, E.value.value); } } } else { - RSG::material_storage->global_shader_uniforms_instance_free(p_instance->self); + RSG::material_storage->global_shader_parameters_instance_free(p_instance->self); p_instance->instance_allocated_shader_uniforms_offset = -1; ERR_FAIL_NULL(geom->geometry_instance); geom->geometry_instance->set_instance_shader_uniforms_offset(-1); @@ -3991,7 +3990,7 @@ bool RendererSceneCull::free(RID p_rid) { if (instance->instance_allocated_shader_uniforms) { //free the used shader parameters - RSG::material_storage->global_shader_uniforms_instance_free(instance->self); + RSG::material_storage->global_shader_parameters_instance_free(instance->self); } update_dirty_instances(); //in case something changed this @@ -4003,7 +4002,7 @@ bool RendererSceneCull::free(RID p_rid) { return true; } -TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) { +TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) { return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size); } diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h index 6fff6827c0..c799553f87 100644 --- a/servers/rendering/renderer_scene_cull.h +++ b/servers/rendering/renderer_scene_cull.h @@ -970,10 +970,10 @@ public: void _update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material); - virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &p_parameter, const Variant &p_value); - virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const; - virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &p_parameter) const; - virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &p_parameter) const; + virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value); + virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const; + virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const; + virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const; _FORCE_INLINE_ void _update_instance(Instance *p_instance); _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); @@ -1055,16 +1055,16 @@ public: _FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data); bool _render_reflection_probe_step(Instance *p_instance, int p_step); - void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr); - void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas); + void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr); + void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas); - void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr); + void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr); void update_dirty_instances(); void render_particle_colliders(); virtual void render_probes(); - TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size); + TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size); //pass to scene render @@ -1125,13 +1125,14 @@ public: PASS1RC(float, environment_get_white, RID) // Fog - PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) + PASS10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float) PASS1RC(bool, environment_get_fog_enabled, RID) PASS1RC(Color, environment_get_fog_light_color, RID) PASS1RC(float, environment_get_fog_light_energy, RID) PASS1RC(float, environment_get_fog_sun_scatter, RID) PASS1RC(float, environment_get_fog_density, RID) + PASS1RC(float, environment_get_fog_sky_affect, RID) PASS1RC(float, environment_get_fog_height, RID) PASS1RC(float, environment_get_fog_height_density, RID) PASS1RC(float, environment_get_fog_aerial_perspective, RID) @@ -1140,7 +1141,7 @@ public: PASS1(environment_set_volumetric_fog_filter_active, bool) // Volumentric Fog - PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float) + PASS14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float) PASS1RC(bool, environment_get_volumetric_fog_enabled, RID) PASS1RC(float, environment_get_volumetric_fog_density, RID) @@ -1151,6 +1152,7 @@ public: PASS1RC(float, environment_get_volumetric_fog_length, RID) PASS1RC(float, environment_get_volumetric_fog_detail_spread, RID) PASS1RC(float, environment_get_volumetric_fog_gi_inject, RID) + PASS1RC(float, environment_get_volumetric_fog_sky_affect, RID) PASS1RC(bool, environment_get_volumetric_fog_temporal_reprojection, RID) PASS1RC(float, environment_get_volumetric_fog_temporal_reprojection_amount, RID) PASS1RC(float, environment_get_volumetric_fog_ambient_inject, RID) @@ -1253,8 +1255,7 @@ public: /* Render Buffers */ - PASS0R(RID, render_buffers_create) - PASS13(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, bool, uint32_t) + PASS0R(Ref<RenderSceneBuffers>, render_buffers_create) PASS1(gi_set_use_half_resolution, bool) /* Shadow Atlas */ diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp index 29a0002a32..f085168df3 100644 --- a/servers/rendering/renderer_scene_render.cpp +++ b/servers/rendering/renderer_scene_render.cpp @@ -308,8 +308,8 @@ float RendererSceneRender::environment_get_white(RID p_env) const { // Fog -void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) { - environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective); +void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) { + environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect); } bool RendererSceneRender::environment_get_fog_enabled(RID p_env) const { @@ -332,6 +332,10 @@ float RendererSceneRender::environment_get_fog_density(RID p_env) const { return environment_storage.environment_get_fog_density(p_env); } +float RendererSceneRender::environment_get_fog_sky_affect(RID p_env) const { + return environment_storage.environment_get_fog_sky_affect(p_env); +} + float RendererSceneRender::environment_get_fog_height(RID p_env) const { return environment_storage.environment_get_fog_height(p_env); } @@ -346,8 +350,8 @@ float RendererSceneRender::environment_get_fog_aerial_perspective(RID p_env) con // Volumetric Fog -void RendererSceneRender::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { - environment_storage.environment_set_volumetric_fog(p_env, p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject); +void RendererSceneRender::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) { + environment_storage.environment_set_volumetric_fog(p_env, p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject, p_sky_affect); } bool RendererSceneRender::environment_get_volumetric_fog_enabled(RID p_env) const { @@ -386,6 +390,10 @@ float RendererSceneRender::environment_get_volumetric_fog_gi_inject(RID p_env) c return environment_storage.environment_get_volumetric_fog_gi_inject(p_env); } +float RendererSceneRender::environment_get_volumetric_fog_sky_affect(RID p_env) const { + return environment_storage.environment_get_volumetric_fog_sky_affect(p_env); +} + bool RendererSceneRender::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const { return environment_storage.environment_get_volumetric_fog_temporal_reprojection(p_env); } diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h index 6684773cbc..9aa4108412 100644 --- a/servers/rendering/renderer_scene_render.h +++ b/servers/rendering/renderer_scene_render.h @@ -36,6 +36,7 @@ #include "servers/rendering/renderer_geometry_instance.h" #include "servers/rendering/renderer_scene.h" #include "servers/rendering/storage/environment_storage.h" +#include "storage/render_scene_buffers.h" #include "storage/utilities.h" class RendererSceneRender { @@ -68,10 +69,10 @@ public: /* SDFGI UPDATE */ - virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0; - virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0; - virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0; - virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0; + virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0; + virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const = 0; + virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0; + virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0; /* SKY API */ @@ -126,18 +127,19 @@ public: float environment_get_white(RID p_env) const; // Fog - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective); + void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect); bool environment_get_fog_enabled(RID p_env) const; Color environment_get_fog_light_color(RID p_env) const; float environment_get_fog_light_energy(RID p_env) const; float environment_get_fog_sun_scatter(RID p_env) const; float environment_get_fog_density(RID p_env) const; + float environment_get_fog_sky_affect(RID p_env) const; float environment_get_fog_height(RID p_env) const; float environment_get_fog_height_density(RID p_env) const; float environment_get_fog_aerial_perspective(RID p_env) const; // Volumetric Fog - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject); + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect); bool environment_get_volumetric_fog_enabled(RID p_env) const; float environment_get_volumetric_fog_density(RID p_env) const; Color environment_get_volumetric_fog_scattering(RID p_env) const; @@ -147,6 +149,7 @@ public: float environment_get_volumetric_fog_length(RID p_env) const; float environment_get_volumetric_fog_detail_spread(RID p_env) const; float environment_get_volumetric_fog_gi_inject(RID p_env) const; + float environment_get_volumetric_fog_sky_affect(RID p_env) const; bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const; float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const; float environment_get_volumetric_fog_ambient_inject(RID p_env) const; @@ -317,7 +320,7 @@ public: void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect); }; - virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0; + virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0; virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0; @@ -326,8 +329,7 @@ public: virtual void set_time(double p_time, double p_step) = 0; virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; - virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0; + virtual Ref<RenderSceneBuffers> render_buffers_create() = 0; virtual void gi_set_use_half_resolution(bool p_enable) = 0; virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; @@ -336,7 +338,7 @@ public: virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0; virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0; - virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0; + virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) = 0; virtual bool free(RID p_rid) = 0; diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index b6f515b223..eacd9bbbc2 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -73,33 +73,36 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport, } Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() { - // We need to sort the viewports in a "topological order", - // children first and parents last, we use the Kahn's algorithm to achieve that. + // We need to sort the viewports in a "topological order", children first and + // parents last. We also need to keep sibling viewports in the original order + // from top to bottom. Vector<Viewport *> result; List<Viewport *> nodes; - for (Viewport *viewport : active_viewports) { + for (int i = active_viewports.size() - 1; i >= 0; --i) { + Viewport *viewport = active_viewports[i]; if (viewport->parent.is_valid()) { continue; } nodes.push_back(viewport); + result.insert(0, viewport); } while (!nodes.is_empty()) { - Viewport *node = nodes[0]; + const Viewport *node = nodes[0]; nodes.pop_front(); - result.insert(0, node); - - for (Viewport *child : active_viewports) { + for (int i = active_viewports.size() - 1; i >= 0; --i) { + Viewport *child = active_viewports[i]; if (child->parent != node->self) { continue; } if (!nodes.find(child)) { nodes.push_back(child); + result.insert(0, child); } } } @@ -110,8 +113,7 @@ Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) { if (p_viewport->render_buffers.is_valid()) { if (p_viewport->size.width == 0 || p_viewport->size.height == 0) { - RSG::scene->free(p_viewport->render_buffers); - p_viewport->render_buffers = RID(); + p_viewport->render_buffers.unref(); } else { const float scaling_3d_scale = p_viewport->scaling_3d_scale; RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode; @@ -177,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; - RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, 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->get_view_count()); + 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->get_view_count()); } } } @@ -715,7 +717,14 @@ void RendererViewport::draw_viewports() { blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>(); } - blit_to_screen_list[vp->viewport_to_screen].push_back(blit); + if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") { + Vector<BlitToScreen> blit_to_screen_vec; + blit_to_screen_vec.push_back(blit); + RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blit_to_screen_vec.ptr(), 1); + RSG::rasterizer->end_frame(true); + } else { + blit_to_screen_list[vp->viewport_to_screen].push_back(blit); + } } } @@ -784,7 +793,9 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn ERR_FAIL_COND(!viewport); viewport->fsr_sharpness = p_sharpness; - _configure_3d_render_buffers(viewport); + if (viewport->render_buffers.is_valid()) { + viewport->render_buffers->set_fsr_sharpness(p_sharpness); + } } void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) { @@ -792,7 +803,9 @@ void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_ ERR_FAIL_COND(!viewport); viewport->texture_mipmap_bias = p_mipmap_bias; - _configure_3d_render_buffers(viewport); + if (viewport->render_buffers.is_valid()) { + viewport->render_buffers->set_texture_mipmap_bias(p_mipmap_bias); + } } void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) { @@ -1128,7 +1141,9 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb return; } viewport->use_debanding = p_use_debanding; - _configure_3d_render_buffers(viewport); + if (viewport->render_buffers.is_valid()) { + viewport->render_buffers->set_use_debanding(p_use_debanding); + } } void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) { @@ -1284,7 +1299,7 @@ bool RendererViewport::free(RID p_rid) { RSG::texture_storage->render_target_free(viewport->render_target); RSG::scene->free(viewport->shadow_atlas); if (viewport->render_buffers.is_valid()) { - RSG::scene->free(viewport->render_buffers); + viewport->render_buffers.unref(); } while (viewport->canvas_map.begin()) { diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index f64b2a986f..a123c70372 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -38,6 +38,7 @@ #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" #include "servers/xr/xr_interface.h" +#include "storage/render_scene_buffers.h" class RendererViewport { public: @@ -64,7 +65,7 @@ public: RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE; RID render_target; RID render_target_texture; - RID render_buffers; + Ref<RenderSceneBuffers> render_buffers; RS::ViewportMSAA msaa_2d = RenderingServer::VIEWPORT_MSAA_DISABLED; RS::ViewportMSAA msaa_3d = RenderingServer::VIEWPORT_MSAA_DISABLED; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 2fefdbff52..dd190437a3 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -235,7 +235,7 @@ RID RenderingDevice::_shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv return shader_create_from_spirv(stage_data); } -RID RenderingDevice::_uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set) { +RID RenderingDevice::_uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) { Vector<Uniform> uniforms; uniforms.resize(p_uniforms.size()); for (int i = 0; i < p_uniforms.size(); i++) { diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 276ba8f247..29e5c9cd77 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -42,7 +42,7 @@ class RDSamplerState; class RDVertexAttribute; class RDShaderSource; class RDShaderSPIRV; -class RDUniforms; +class RDUniform; class RDPipelineRasterizationState; class RDPipelineMultisampleState; class RDPipelineDepthStencilState; @@ -464,6 +464,32 @@ public: Vector<DataFormat> shareable_formats; bool is_resolve_buffer = false; + bool operator==(const TextureFormat &b) const { + if (format != b.format) { + return false; + } else if (width != b.width) { + return false; + } else if (height != b.height) { + return false; + } else if (depth != b.depth) { + return false; + } else if (array_layers != b.array_layers) { + return false; + } else if (mipmaps != b.mipmaps) { + return false; + } else if (texture_type != b.texture_type) { + return false; + } else if (samples != b.samples) { + return false; + } else if (usage_bits != b.usage_bits) { + return false; + } else if (shareable_formats != b.shareable_formats) { + return false; + } else { + return true; + } + } + TextureFormat() { format = DATA_FORMAT_R8_UNORM; width = 1; @@ -1288,7 +1314,7 @@ protected: Vector<uint8_t> _shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_bytecode, const String &p_shader_name = ""); RID _shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv, const String &p_shader_name = ""); - RID _uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set); + RID _uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set); Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL); diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index 1f686069bd..9103b0cf56 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -91,7 +91,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { RSG::viewport->draw_viewports(); RSG::canvas_render->update(); - RSG::rasterizer->end_frame(p_swap_buffers); + if (OS::get_singleton()->get_current_rendering_driver_name() != "opengl3") { + // Already called for gl_compatibility renderer. + RSG::rasterizer->end_frame(p_swap_buffers); + } XRServer *xr_server = XRServer::get_singleton(); if (xr_server != nullptr) { diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index 40912805dc..dfe16431bd 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -227,11 +227,11 @@ public: FUNC2(shader_set_path_hint, RID, const String &) FUNC1RC(String, shader_get_code, RID) - FUNC2SC(shader_get_shader_uniform_list, RID, List<PropertyInfo> *) + FUNC2SC(get_shader_parameter_list, RID, List<PropertyInfo> *) - FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int) - FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int) - FUNC2RC(Variant, shader_get_param_default, RID, const StringName &) + FUNC4(shader_set_default_texture_parameter, RID, const StringName &, RID, int) + FUNC3RC(RID, shader_get_default_texture_parameter, RID, const StringName &, int) + FUNC2RC(Variant, shader_get_parameter_default, RID, const StringName &) FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID) @@ -695,8 +695,8 @@ public: FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID) - FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) - FUNC13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float) + FUNC10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float) + FUNC14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float) FUNC2(environment_set_volumetric_fog_volume_size, int, int) FUNC1(environment_set_volumetric_fog_filter_active, bool) @@ -783,12 +783,12 @@ public: FUNC4(instance_geometry_set_lightmap, RID, RID, const Rect2 &, int) FUNC2(instance_geometry_set_lod_bias, RID, float) FUNC2(instance_geometry_set_transparency, RID, float) - FUNC3(instance_geometry_set_shader_uniform, RID, const StringName &, const Variant &) - FUNC2RC(Variant, instance_geometry_get_shader_uniform, RID, const StringName &) - FUNC2RC(Variant, instance_geometry_get_shader_uniform_default_value, RID, const StringName &) - FUNC2C(instance_geometry_get_shader_uniform_list, RID, List<PropertyInfo> *) + FUNC3(instance_geometry_set_shader_parameter, RID, const StringName &, const Variant &) + FUNC2RC(Variant, instance_geometry_get_shader_parameter, RID, const StringName &) + FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &) + FUNC2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *) - FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &) + FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const TypedArray<RID> &, const Size2i &) FUNC1(gi_set_use_half_resolution, bool) @@ -919,16 +919,16 @@ public: #define ServerName RendererMaterialStorage #define server_name RSG::material_storage - FUNC3(global_shader_uniform_add, const StringName &, GlobalShaderUniformType, const Variant &) - FUNC1(global_shader_uniform_remove, const StringName &) - FUNC0RC(Vector<StringName>, global_shader_uniform_get_list) - FUNC2(global_shader_uniform_set, const StringName &, const Variant &) - FUNC2(global_shader_uniform_set_override, const StringName &, const Variant &) - FUNC1RC(GlobalShaderUniformType, global_shader_uniform_get_type, const StringName &) - FUNC1RC(Variant, global_shader_uniform_get, const StringName &) + FUNC3(global_shader_parameter_add, const StringName &, GlobalShaderParameterType, const Variant &) + FUNC1(global_shader_parameter_remove, const StringName &) + FUNC0RC(Vector<StringName>, global_shader_parameter_get_list) + FUNC2(global_shader_parameter_set, const StringName &, const Variant &) + FUNC2(global_shader_parameter_set_override, const StringName &, const Variant &) + FUNC1RC(GlobalShaderParameterType, global_shader_parameter_get_type, const StringName &) + FUNC1RC(Variant, global_shader_parameter_get, const StringName &) - FUNC1(global_shader_uniforms_load_settings, bool) - FUNC0(global_shader_uniforms_clear) + FUNC1(global_shader_parameters_load_settings, bool) + FUNC0(global_shader_parameters_clear) #undef server_name #undef ServerName diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp index 7b33a13ec3..ab5b8af794 100644 --- a/servers/rendering/shader_compiler.cpp +++ b/servers/rendering/shader_compiler.cpp @@ -1349,7 +1349,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene } ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) { - RS::GlobalShaderUniformType gvt = RS::get_singleton()->global_shader_uniform_get_type(p_type); + RS::GlobalShaderParameterType gvt = RS::get_singleton()->global_shader_parameter_get_type(p_type); return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt); } diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 2bbc5e4dfb..6754d84cd4 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -257,6 +257,7 @@ enum ContextFlag : uint32_t { CF_UNIFORM_KEYWORD = 2048U, // "uniform" CF_CONST_KEYWORD = 4096U, // "const" CF_UNIFORM_QUALIFIER = 8192U, // "<x> uniform float t;" + CF_SHADER_TYPE = 16384U, // "shader_type" }; const uint32_t KCF_DATATYPE = CF_BLOCK | CF_GLOBAL_SPACE | CF_DATATYPE | CF_FUNC_DECL_PARAM_TYPE | CF_UNIFORM_TYPE; @@ -318,7 +319,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { { TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} }, { TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} }, { TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} }, - { TK_SHADER_TYPE, "shader_type", CF_GLOBAL_SPACE, {}, {} }, + { TK_SHADER_TYPE, "shader_type", CF_SHADER_TYPE, {}, {} }, { TK_RENDER_MODE, "render_mode", CF_GLOBAL_SPACE, {}, {} }, // uniform qualifiers @@ -1068,7 +1069,7 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) { result = "hint_range"; } break; case ShaderNode::Uniform::HINT_SOURCE_COLOR: { - result = "hint_color"; + result = "source_color"; } break; case ShaderNode::Uniform::HINT_NORMAL: { result = "hint_normal"; @@ -1170,6 +1171,10 @@ void ShaderLanguage::clear() { last_type = IDENTIFIER_MAX; current_uniform_group_name = ""; current_uniform_subgroup_name = ""; + current_uniform_hint = ShaderNode::Uniform::HINT_NONE; + current_uniform_filter = FILTER_DEFAULT; + current_uniform_repeat = REPEAT_DEFAULT; + current_uniform_instance_index_defined = false; completion_type = COMPLETION_NONE; completion_block = nullptr; @@ -1183,7 +1188,7 @@ void ShaderLanguage::clear() { include_positions.push_back(FilePosition()); #ifdef DEBUG_ENABLED - keyword_completion_context = CF_GLOBAL_SPACE; + keyword_completion_context = CF_UNSPECIFIED; used_constants.clear(); used_varyings.clear(); used_uniforms.clear(); @@ -7821,6 +7826,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f Token next; if (!is_shader_inc) { +#ifdef DEBUG_ENABLED + keyword_completion_context = CF_SHADER_TYPE; +#endif // DEBUG_ENABLED tk = _get_token(); if (tk.type != TK_SHADER_TYPE) { @@ -8613,6 +8621,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f } custom_instance_index = tk.constant; + current_uniform_instance_index_defined = true; if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) { _set_error(vformat(RTR("Allowed instance uniform indices must be within [0..%d] range."), MAX_INSTANCE_UNIFORM_INDICES - 1)); @@ -8678,6 +8687,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } else { uniform.hint = new_hint; + current_uniform_hint = new_hint; } } @@ -8691,6 +8701,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } else { uniform.filter = new_filter; + current_uniform_filter = new_filter; } } @@ -8704,6 +8715,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f return ERR_PARSE_ERROR; } else { uniform.repeat = new_repeat; + current_uniform_repeat = new_repeat; } } @@ -8771,6 +8783,11 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f keyword_completion_context = CF_GLOBAL_SPACE; #endif // DEBUG_ENABLED completion_type = COMPLETION_NONE; + + current_uniform_hint = ShaderNode::Uniform::HINT_NONE; + current_uniform_filter = FILTER_DEFAULT; + current_uniform_repeat = REPEAT_DEFAULT; + current_uniform_instance_index_defined = false; } else { // varying ShaderNode::Varying varying; varying.type = type; @@ -10307,28 +10324,33 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ } break; case COMPLETION_HINT: { if (completion_base == DataType::TYPE_VEC3 || completion_base == DataType::TYPE_VEC4) { - ScriptLanguage::CodeCompletionOption option("source_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); - r_options->push_back(option); + if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { + ScriptLanguage::CodeCompletionOption option("source_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + r_options->push_back(option); + } } else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) { - ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); + if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { + ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); - if (completion_base == DataType::TYPE_INT) { - option.insert_text = "hint_range(0, 100, 1)"; - } else { - option.insert_text = "hint_range(0.0, 1.0, 0.1)"; - } + if (completion_base == DataType::TYPE_INT) { + option.insert_text = "hint_range(0, 100, 1)"; + } else { + option.insert_text = "hint_range(0.0, 1.0, 0.1)"; + } - r_options->push_back(option); + r_options->push_back(option); + } } else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT)) && !completion_base_array) { - static Vector<String> options; - - if (options.is_empty()) { + Vector<String> options; + if (current_uniform_filter == FILTER_DEFAULT) { options.push_back("filter_linear"); options.push_back("filter_linear_mipmap"); options.push_back("filter_linear_mipmap_anisotropic"); options.push_back("filter_nearest"); options.push_back("filter_nearest_mipmap"); options.push_back("filter_nearest_mipmap_anisotropic"); + } + if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) { options.push_back("hint_anisotropy"); options.push_back("hint_default_black"); options.push_back("hint_default_white"); @@ -10344,6 +10366,8 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ options.push_back("hint_normal_roughness_texture"); options.push_back("hint_depth_texture"); options.push_back("source_color"); + } + if (current_uniform_repeat == REPEAT_DEFAULT) { options.push_back("repeat_enable"); options.push_back("repeat_disable"); } @@ -10353,7 +10377,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_ r_options->push_back(option); } } - if (!completion_base_array) { + if (!completion_base_array && !current_uniform_instance_index_defined) { ScriptLanguage::CodeCompletionOption option("instance_index", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT); option.insert_text = "instance_index(0)"; r_options->push_back(option); diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 75b713d167..e9f8c3b289 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -1050,6 +1050,10 @@ private: }; CompletionType completion_type; + ShaderNode::Uniform::Hint current_uniform_hint = ShaderNode::Uniform::HINT_NONE; + TextureFilter current_uniform_filter = FILTER_DEFAULT; + TextureRepeat current_uniform_repeat = REPEAT_DEFAULT; + bool current_uniform_instance_index_defined = false; int completion_line = 0; BlockNode *completion_block = nullptr; DataType completion_base; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 43c483a00d..cd063f91ac 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -340,6 +340,11 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_VELOCITY"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_COLOR"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_CUSTOM"] = constt(ShaderLanguage::TYPE_UINT); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_POSITION"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_ROT_SCALE"] = constt(ShaderLanguage::TYPE_BOOL); shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL); @@ -385,6 +390,7 @@ ShaderTypes::ShaderTypes() { emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("custom", ShaderLanguage::TYPE_VEC4)); emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("flags", ShaderLanguage::TYPE_UINT)); emit_vertex_func.return_type = ShaderLanguage::TYPE_BOOL; //whether it could emit + shader_modes[RS::SHADER_PARTICLES].functions["start"].stage_functions["emit_subparticle"] = emit_vertex_func; shader_modes[RS::SHADER_PARTICLES].functions["process"].stage_functions["emit_subparticle"] = emit_vertex_func; } @@ -444,6 +450,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_half_res_pass") }); shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_quarter_res_pass") }); shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("disable_fog") }); + shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_debanding") }); } /************ FOG **************************/ diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp index 19cb067025..9b1842f1d9 100644 --- a/servers/rendering/storage/environment_storage.cpp +++ b/servers/rendering/storage/environment_storage.cpp @@ -205,7 +205,7 @@ float RendererEnvironmentStorage::environment_get_white(RID p_env) const { // Fog -void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) { +void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective, float p_sky_affect) { Environment *env = environment_owner.get_or_null(p_env); ERR_FAIL_COND(!env); env->fog_enabled = p_enable; @@ -216,6 +216,7 @@ void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, c env->fog_height = p_height; env->fog_height_density = p_height_density; env->fog_aerial_perspective = p_fog_aerial_perspective; + env->fog_sky_affect = p_sky_affect; } bool RendererEnvironmentStorage::environment_get_fog_enabled(RID p_env) const { @@ -266,9 +267,15 @@ float RendererEnvironmentStorage::environment_get_fog_aerial_perspective(RID p_e return env->fog_aerial_perspective; } +float RendererEnvironmentStorage::environment_get_fog_sky_affect(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->fog_sky_affect; +} + // Volumetric Fog -void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) { +void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) { Environment *env = environment_owner.get_or_null(p_env); ERR_FAIL_COND(!env); env->volumetric_fog_enabled = p_enable; @@ -283,6 +290,7 @@ void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool env->volumetric_fog_temporal_reprojection = p_temporal_reprojection; env->volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount; env->volumetric_fog_ambient_inject = p_ambient_inject; + env->volumetric_fog_sky_affect = p_sky_affect; } bool RendererEnvironmentStorage::environment_get_volumetric_fog_enabled(RID p_env) const { @@ -339,6 +347,12 @@ float RendererEnvironmentStorage::environment_get_volumetric_fog_gi_inject(RID p return env->volumetric_fog_gi_inject; } +float RendererEnvironmentStorage::environment_get_volumetric_fog_sky_affect(RID p_env) const { + Environment *env = environment_owner.get_or_null(p_env); + ERR_FAIL_COND_V(!env, 0.0); + return env->volumetric_fog_sky_affect; +} + bool RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const { Environment *env = environment_owner.get_or_null(p_env); ERR_FAIL_COND_V(!env, true); diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h index 2821d299a8..17bde94902 100644 --- a/servers/rendering/storage/environment_storage.h +++ b/servers/rendering/storage/environment_storage.h @@ -66,6 +66,7 @@ private: float fog_light_energy = 1.0; float fog_sun_scatter = 0.0; float fog_density = 0.01; + float fog_sky_affect = 1.0; float fog_height = 0.0; float fog_height_density = 0.0; //can be negative to invert effect float fog_aerial_perspective = 0.0; @@ -81,6 +82,7 @@ private: float volumetric_fog_detail_spread = 2.0; float volumetric_fog_gi_inject = 1.0; float volumetric_fog_ambient_inject = 0.0; + float volumetric_fog_sky_affect = 1.0; bool volumetric_fog_temporal_reprojection = true; float volumetric_fog_temporal_reprojection_amount = 0.9; @@ -190,18 +192,19 @@ public: float environment_get_white(RID p_env) const; // Fog - void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective); + void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect); bool environment_get_fog_enabled(RID p_env) const; Color environment_get_fog_light_color(RID p_env) const; float environment_get_fog_light_energy(RID p_env) const; float environment_get_fog_sun_scatter(RID p_env) const; float environment_get_fog_density(RID p_env) const; + float environment_get_fog_sky_affect(RID p_env) const; float environment_get_fog_height(RID p_env) const; float environment_get_fog_height_density(RID p_env) const; float environment_get_fog_aerial_perspective(RID p_env) const; // Volumetric Fog - void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject); + void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect); bool environment_get_volumetric_fog_enabled(RID p_env) const; float environment_get_volumetric_fog_density(RID p_env) const; Color environment_get_volumetric_fog_scattering(RID p_env) const; @@ -211,6 +214,7 @@ public: float environment_get_volumetric_fog_length(RID p_env) const; float environment_get_volumetric_fog_detail_spread(RID p_env) const; float environment_get_volumetric_fog_gi_inject(RID p_env) const; + float environment_get_volumetric_fog_sky_affect(RID p_env) const; bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const; float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const; float environment_get_volumetric_fog_ambient_inject(RID p_env) const; diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h index ad8e3e79bf..396668c9ed 100644 --- a/servers/rendering/storage/material_storage.h +++ b/servers/rendering/storage/material_storage.h @@ -39,21 +39,21 @@ public: virtual ~RendererMaterialStorage(){}; /* GLOBAL SHADER UNIFORM API */ - virtual void global_shader_uniform_add(const StringName &p_name, RS::GlobalShaderUniformType p_type, const Variant &p_value) = 0; - virtual void global_shader_uniform_remove(const StringName &p_name) = 0; - virtual Vector<StringName> global_shader_uniform_get_list() const = 0; + virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) = 0; + virtual void global_shader_parameter_remove(const StringName &p_name) = 0; + virtual Vector<StringName> global_shader_parameter_get_list() const = 0; - virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0; - virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0; - virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0; - virtual RS::GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0; + virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) = 0; + virtual Variant global_shader_parameter_get(const StringName &p_name) const = 0; + virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const = 0; - virtual void global_shader_uniforms_load_settings(bool p_load_textures = true) = 0; - virtual void global_shader_uniforms_clear() = 0; + virtual void global_shader_parameters_load_settings(bool p_load_textures = true) = 0; + virtual void global_shader_parameters_clear() = 0; - virtual int32_t global_shader_uniforms_instance_allocate(RID p_instance) = 0; - virtual void global_shader_uniforms_instance_free(RID p_instance) = 0; - virtual void global_shader_uniforms_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; + virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) = 0; + virtual void global_shader_parameters_instance_free(RID p_instance) = 0; + virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0; /* SHADER API */ virtual RID shader_allocate() = 0; @@ -63,11 +63,11 @@ public: virtual void shader_set_code(RID p_shader, const String &p_code) = 0; virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0; virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0; - virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; + virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0; + virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const = 0; + virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const = 0; virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0; @@ -94,7 +94,7 @@ public: Variant default_value; }; - virtual void material_get_instance_shader_uniforms(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; + virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0; virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0; }; diff --git a/servers/rendering/storage/render_scene_buffers.cpp b/servers/rendering/storage/render_scene_buffers.cpp new file mode 100644 index 0000000000..104700090f --- /dev/null +++ b/servers/rendering/storage/render_scene_buffers.cpp @@ -0,0 +1,51 @@ +/*************************************************************************/ +/* render_scene_buffers.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "render_scene_buffers.h" + +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::set_fsr_sharpness(float p_fsr_sharpness) { + GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness); +} + +void RenderSceneBuffers::set_texture_mipmap_bias(float p_texture_mipmap_bias) { + GDVIRTUAL_CALL(_set_texture_mipmap_bias, p_texture_mipmap_bias); +} + +void RenderSceneBuffers::set_use_debanding(bool p_use_debanding) { + GDVIRTUAL_CALL(_set_use_debanding, p_use_debanding); +} diff --git a/servers/rendering/storage/render_scene_buffers.h b/servers/rendering/storage/render_scene_buffers.h new file mode 100644 index 0000000000..e28e3201ae --- /dev/null +++ b/servers/rendering/storage/render_scene_buffers.h @@ -0,0 +1,60 @@ +/*************************************************************************/ +/* render_scene_buffers.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDER_SCENE_BUFFERS_H +#define RENDER_SCENE_BUFFERS_H + +#include "core/object/ref_counted.h" +#include "servers/rendering_server.h" + +class RenderSceneBuffers : public RefCounted { + GDCLASS(RenderSceneBuffers, RefCounted); + +protected: + static void _bind_methods(); + + GDVIRTUAL10(_configure, RID, Size2i, Size2i, 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) + +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); + + // 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); + virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias); + virtual void set_use_debanding(bool p_use_debanding); +}; + +#endif // RENDER_SCENE_BUFFERS_H diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a840375393..cbcfc8fe49 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -95,7 +95,7 @@ PackedInt64Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from return to_int_array(ids); } -PackedInt64Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const { +PackedInt64Array RenderingServer::_instances_cull_convex_bind(const TypedArray<Plane> &p_convex, RID p_scenario) const { if (RSG::threaded) { WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall."); } @@ -1114,7 +1114,8 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t for (int j = 0; j < p_vertex_len; j++) { const uint32_t v = *(const uint32_t *)&r[j * vertex_elem_size + offsets[i]]; - w[j] = Vector3((v & 0x3FF) / 1023.0, ((v >> 10) & 0x3FF) / 1023.0, ((v >> 20) & 0x3FF) / 1023.0) * Vector3(2, 2, 2) - Vector3(1, 1, 1); + + w[j] = Vector3::octahedron_decode(Vector2((v & 0xFFFF) / 65535.0, ((v >> 16) & 0xFFFF) / 65535.0)); } ret[i] = arr; @@ -1129,11 +1130,12 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t for (int j = 0; j < p_vertex_len; j++) { const uint32_t v = *(const uint32_t *)&r[j * vertex_elem_size + offsets[i]]; - - w[j * 4 + 0] = ((v & 0x3FF) / 1023.0) * 2.0 - 1.0; - w[j * 4 + 1] = (((v >> 10) & 0x3FF) / 1023.0) * 2.0 - 1.0; - w[j * 4 + 2] = (((v >> 20) & 0x3FF) / 1023.0) * 2.0 - 1.0; - w[j * 4 + 3] = ((v >> 30) / 3.0) * 2.0 - 1.0; + float tangent_sign; + Vector3 res = Vector3::octahedron_tangent_decode(Vector2((v & 0xFFFF) / 65535.0, ((v >> 16) & 0xFFFF) / 65535.0), &tangent_sign); + w[j * 4 + 0] = res.x; + w[j * 4 + 1] = res.y; + w[j * 4 + 2] = res.z; + w[j * 4 + 3] = tangent_sign; } ret[i] = arr; @@ -1400,7 +1402,7 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su } #endif -int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type) { +int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderParameterType p_type) { switch (p_type) { case RS::GLOBAL_VAR_TYPE_BOOL: return ShaderLanguage::TYPE_BOOL; @@ -1501,9 +1503,9 @@ TypedArray<Image> RenderingServer::_texture_3d_get(RID p_texture) const { return ret; } -TypedArray<Dictionary> RenderingServer::_shader_get_shader_uniform_list(RID p_shader) const { +TypedArray<Dictionary> RenderingServer::_shader_get_shader_parameter_list(RID p_shader) const { List<PropertyInfo> l; - shader_get_shader_uniform_list(p_shader, &l); + get_shader_parameter_list(p_shader, &l); return convert_property_list(&l); } @@ -1626,14 +1628,14 @@ Dictionary RenderingServer::_mesh_get_surface(RID p_mesh, int p_idx) { return d; } -TypedArray<Dictionary> RenderingServer::_instance_geometry_get_shader_uniform_list(RID p_instance) const { +TypedArray<Dictionary> RenderingServer::_instance_geometry_get_shader_parameter_list(RID p_instance) const { List<PropertyInfo> params; - instance_geometry_get_shader_uniform_list(p_instance, ¶ms); + instance_geometry_get_shader_parameter_list(p_instance, ¶ms); return convert_property_list(¶ms); } TypedArray<Image> RenderingServer::_bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) { - Vector<RID> mat_overrides; + TypedArray<RID> mat_overrides; for (int i = 0; i < p_material_overrides.size(); i++) { mat_overrides.push_back(p_material_overrides[i]); } @@ -1702,11 +1704,11 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &RenderingServer::shader_set_code); ClassDB::bind_method(D_METHOD("shader_set_path_hint", "shader", "path"), &RenderingServer::shader_set_path_hint); ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &RenderingServer::shader_get_code); - ClassDB::bind_method(D_METHOD("shader_get_shader_uniform_list", "shader"), &RenderingServer::_shader_get_shader_uniform_list); - ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default); + ClassDB::bind_method(D_METHOD("get_shader_parameter_list", "shader"), &RenderingServer::_shader_get_shader_parameter_list); + ClassDB::bind_method(D_METHOD("shader_get_parameter_default", "shader", "name"), &RenderingServer::shader_get_parameter_default); - ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param", "index"), &RenderingServer::shader_get_default_texture_param, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("shader_set_default_texture_parameter", "shader", "name", "texture", "index"), &RenderingServer::shader_set_default_texture_parameter, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("shader_get_default_texture_parameter", "shader", "name", "index"), &RenderingServer::shader_get_default_texture_parameter, DEFVAL(0)); BIND_ENUM_CONSTANT(SHADER_SPATIAL); BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); @@ -2335,9 +2337,9 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment); ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr); ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao); - ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective"), &RenderingServer::environment_set_fog); + ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::environment_set_fog); ClassDB::bind_method(D_METHOD("environment_set_sdfgi", "env", "enable", "cascades", "min_cell_size", "y_scale", "use_occlusion", "bounce_feedback", "read_sky", "energy", "normal_bias", "probe_bias"), &RenderingServer::environment_set_sdfgi); - ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject"), &RenderingServer::environment_set_volumetric_fog); + ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject", "sky_affect"), &RenderingServer::environment_set_volumetric_fog); ClassDB::bind_method(D_METHOD("environment_glow_set_use_bicubic_upscale", "enable"), &RenderingServer::environment_glow_set_use_bicubic_upscale); ClassDB::bind_method(D_METHOD("environment_glow_set_use_high_quality", "enable"), &RenderingServer::environment_glow_set_use_high_quality); @@ -2490,10 +2492,10 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("instance_geometry_set_lightmap", "instance", "lightmap", "lightmap_uv_scale", "lightmap_slice"), &RenderingServer::instance_geometry_set_lightmap); ClassDB::bind_method(D_METHOD("instance_geometry_set_lod_bias", "instance", "lod_bias"), &RenderingServer::instance_geometry_set_lod_bias); - ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_uniform", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_uniform); - ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform); - ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_uniform_default_value); - ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_uniform_list", "instance"), &RenderingServer::_instance_geometry_get_shader_uniform_list); + ClassDB::bind_method(D_METHOD("instance_geometry_set_shader_parameter", "instance", "parameter", "value"), &RenderingServer::instance_geometry_set_shader_parameter); + ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter); + ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_default_value", "instance", "parameter"), &RenderingServer::instance_geometry_get_shader_parameter_default_value); + ClassDB::bind_method(D_METHOD("instance_geometry_get_shader_parameter_list", "instance"), &RenderingServer::_instance_geometry_get_shader_parameter_list); ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID())); ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID())); @@ -2690,13 +2692,13 @@ void RenderingServer::_bind_methods() { /* GLOBAL SHADER UNIFORMS */ - ClassDB::bind_method(D_METHOD("global_shader_uniform_add", "name", "type", "default_value"), &RenderingServer::global_shader_uniform_add); - ClassDB::bind_method(D_METHOD("global_shader_uniform_remove", "name"), &RenderingServer::global_shader_uniform_remove); - ClassDB::bind_method(D_METHOD("global_shader_uniform_get_list"), &RenderingServer::global_shader_uniform_get_list); - ClassDB::bind_method(D_METHOD("global_shader_uniform_set", "name", "value"), &RenderingServer::global_shader_uniform_set); - ClassDB::bind_method(D_METHOD("global_shader_uniform_set_override", "name", "value"), &RenderingServer::global_shader_uniform_set_override); - ClassDB::bind_method(D_METHOD("global_shader_uniform_get", "name"), &RenderingServer::global_shader_uniform_get); - ClassDB::bind_method(D_METHOD("global_shader_uniform_get_type", "name"), &RenderingServer::global_shader_uniform_get_type); + ClassDB::bind_method(D_METHOD("global_shader_parameter_add", "name", "type", "default_value"), &RenderingServer::global_shader_parameter_add); + ClassDB::bind_method(D_METHOD("global_shader_parameter_remove", "name"), &RenderingServer::global_shader_parameter_remove); + ClassDB::bind_method(D_METHOD("global_shader_parameter_get_list"), &RenderingServer::global_shader_parameter_get_list); + ClassDB::bind_method(D_METHOD("global_shader_parameter_set", "name", "value"), &RenderingServer::global_shader_parameter_set); + ClassDB::bind_method(D_METHOD("global_shader_parameter_set_override", "name", "value"), &RenderingServer::global_shader_parameter_set_override); + ClassDB::bind_method(D_METHOD("global_shader_parameter_get", "name"), &RenderingServer::global_shader_parameter_get); + ClassDB::bind_method(D_METHOD("global_shader_parameter_get_type", "name"), &RenderingServer::global_shader_parameter_get_type); BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BOOL); BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC2); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 8cefad7cb5..67ba407775 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -173,11 +173,11 @@ public: virtual void shader_set_code(RID p_shader, const String &p_code) = 0; virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0; virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_shader_uniform_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; - virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0; + virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0; + virtual Variant shader_get_parameter_default(RID p_shader, const StringName &p_param) const = 0; - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index = 0) const = 0; + virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0; + virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index = 0) const = 0; struct ShaderNativeSourceCode { struct Version { @@ -1120,9 +1120,9 @@ public: virtual void environment_set_sdfgi_frames_to_update_light(EnvironmentSDFGIFramesToUpdateLight p_update) = 0; - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0; + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) = 0; - virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0; + virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0; virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0; virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0; @@ -1223,7 +1223,7 @@ public: PackedInt64Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const; PackedInt64Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; - PackedInt64Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const; + PackedInt64Array _instances_cull_convex_bind(const TypedArray<Plane> &p_convex, RID p_scenario = RID()) const; enum InstanceFlags { INSTANCE_FLAG_USE_BAKED_LIGHT, @@ -1255,10 +1255,10 @@ public: virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias) = 0; virtual void instance_geometry_set_transparency(RID p_instance, float p_transparency) = 0; - virtual void instance_geometry_set_shader_uniform(RID p_instance, const StringName &, const Variant &p_value) = 0; - virtual Variant instance_geometry_get_shader_uniform(RID p_instance, const StringName &) const = 0; - virtual Variant instance_geometry_get_shader_uniform_default_value(RID p_instance, const StringName &) const = 0; - virtual void instance_geometry_get_shader_uniform_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; + virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &, const Variant &p_value) = 0; + virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &) const = 0; + virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &) const = 0; + virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const = 0; /* Bake 3D objects */ @@ -1269,7 +1269,7 @@ public: BAKE_CHANNEL_EMISSION }; - virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0; + virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) = 0; /* CANVAS (2D) */ @@ -1441,7 +1441,7 @@ public: /* GLOBAL SHADER UNIFORMS */ - enum GlobalShaderUniformType { + enum GlobalShaderParameterType { GLOBAL_VAR_TYPE_BOOL, GLOBAL_VAR_TYPE_BVEC2, GLOBAL_VAR_TYPE_BVEC3, @@ -1473,20 +1473,20 @@ public: GLOBAL_VAR_TYPE_MAX }; - virtual void global_shader_uniform_add(const StringName &p_name, GlobalShaderUniformType p_type, const Variant &p_value) = 0; - virtual void global_shader_uniform_remove(const StringName &p_name) = 0; - virtual Vector<StringName> global_shader_uniform_get_list() const = 0; + virtual void global_shader_parameter_add(const StringName &p_name, GlobalShaderParameterType p_type, const Variant &p_value) = 0; + virtual void global_shader_parameter_remove(const StringName &p_name) = 0; + virtual Vector<StringName> global_shader_parameter_get_list() const = 0; - virtual void global_shader_uniform_set(const StringName &p_name, const Variant &p_value) = 0; - virtual void global_shader_uniform_set_override(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) = 0; + virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) = 0; - virtual Variant global_shader_uniform_get(const StringName &p_name) const = 0; - virtual GlobalShaderUniformType global_shader_uniform_get_type(const StringName &p_name) const = 0; + virtual Variant global_shader_parameter_get(const StringName &p_name) const = 0; + virtual GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const = 0; - virtual void global_shader_uniforms_load_settings(bool p_load_textures) = 0; - virtual void global_shader_uniforms_clear() = 0; + virtual void global_shader_parameters_load_settings(bool p_load_textures) = 0; + virtual void global_shader_parameters_clear() = 0; - static int global_shader_uniform_type_get_shader_datatype(GlobalShaderUniformType p_type); + static int global_shader_uniform_type_get_shader_datatype(GlobalShaderParameterType p_type); /* FREE */ @@ -1583,11 +1583,11 @@ private: RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data); void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data); TypedArray<Image> _texture_3d_get(RID p_texture) const; - TypedArray<Dictionary> _shader_get_shader_uniform_list(RID p_shader) const; + TypedArray<Dictionary> _shader_get_shader_parameter_list(RID p_shader) const; RID _mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count); void _mesh_add_surface(RID p_mesh, const Dictionary &p_surface); Dictionary _mesh_get_surface(RID p_mesh, int p_idx); - TypedArray<Dictionary> _instance_geometry_get_shader_uniform_list(RID p_instance) const; + TypedArray<Dictionary> _instance_geometry_get_shader_parameter_list(RID p_instance) const; TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size); void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses); }; @@ -1662,7 +1662,7 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode); VARIANT_ENUM_CAST(RenderingServer::CanvasLightBlendMode); VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter); VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode); -VARIANT_ENUM_CAST(RenderingServer::GlobalShaderUniformType); +VARIANT_ENUM_CAST(RenderingServer::GlobalShaderParameterType); VARIANT_ENUM_CAST(RenderingServer::RenderingInfo); VARIANT_ENUM_CAST(RenderingServer::Features); VARIANT_ENUM_CAST(RenderingServer::CanvasTextureChannel); diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 74ae2bfff0..ebd35b0f75 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -1136,7 +1136,7 @@ int64_t TextServerExtension::shaped_text_get_spacing(const RID &p_shaped, TextSe return 0; } -bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) { +bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) { bool ret; if (GDVIRTUAL_CALL(shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret)) { return ret; @@ -1176,7 +1176,7 @@ Variant TextServerExtension::shaped_get_span_meta(const RID &p_shaped, int64_t p return false; } -void TextServerExtension::shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) { +void TextServerExtension::shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) { GDVIRTUAL_CALL(shaped_set_span_update_font, p_shaped, p_index, p_fonts, p_size, p_opentype_features); } diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 6a2c199898..700d08f7d7 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -378,19 +378,19 @@ public: GDVIRTUAL3(shaped_text_set_spacing, RID, SpacingType, int64_t); GDVIRTUAL2RC(int64_t, shaped_text_get_spacing, RID, SpacingType); - virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override; + virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override; virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override; virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override; - GDVIRTUAL7R(bool, shaped_text_add_string, RID, const String &, const Array &, int64_t, const Dictionary &, const String &, const Variant &); + GDVIRTUAL7R(bool, shaped_text_add_string, RID, const String &, const TypedArray<RID> &, int64_t, const Dictionary &, const String &, const Variant &); GDVIRTUAL5R(bool, shaped_text_add_object, RID, const Variant &, const Size2 &, InlineAlignment, int64_t); GDVIRTUAL4R(bool, shaped_text_resize_object, RID, const Variant &, const Size2 &, InlineAlignment); virtual int64_t shaped_get_span_count(const RID &p_shaped) const override; virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const override; - virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) override; + virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) override; GDVIRTUAL1RC(int64_t, shaped_get_span_count, RID); GDVIRTUAL2RC(Variant, shaped_get_span_meta, RID, int64_t); - GDVIRTUAL5(shaped_set_span_update_font, RID, int64_t, const Array &, int64_t, const Dictionary &); + GDVIRTUAL5(shaped_set_span_update_font, RID, int64_t, const TypedArray<RID> &, int64_t, const Dictionary &); virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override; virtual RID shaped_text_get_parent(const RID &p_shaped) const override; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 9df74b1b20..660247839c 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -683,7 +683,9 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped int line_start = MAX(p_start, range.x); int prev_safe_break = 0; int last_safe_break = -1; + int word_count = 0; int chunk = 0; + bool trim_next = false; int l_size = shaped_text_get_glyph_count(p_shaped); const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); @@ -698,8 +700,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = prev_safe_break; int end_pos = last_safe_break; - - while ((start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { + while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { start_pos += l_gl[start_pos].count; } while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { @@ -707,6 +708,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped } lines.push_back(l_gl[start_pos].start); lines.push_back(l_gl[end_pos].end); + trim_next = true; } else { lines.push_back(line_start); lines.push_back(l_gl[last_safe_break].end); @@ -716,6 +718,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped i = last_safe_break; last_safe_break = -1; width = 0; + word_count = 0; chunk++; if (chunk >= p_width.size()) { chunk = 0; @@ -730,8 +733,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = prev_safe_break; int end_pos = i; - - while ((start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { + while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { start_pos += l_gl[start_pos].count; } while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { @@ -739,6 +741,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped } lines.push_back(l_gl[start_pos].start); lines.push_back(l_gl[end_pos].end); + trim_next = false; } else { lines.push_back(line_start); lines.push_back(l_gl[i].end); @@ -757,9 +760,10 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped if (p_break_flags.has_flag(BREAK_WORD_BOUND)) { if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { last_safe_break = i; + word_count++; } } - if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND)) { + if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND) && word_count == 0) { last_safe_break = i; } } @@ -771,19 +775,14 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1; int end_pos = l_size - 1; - - while ((start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { + while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { start_pos += l_gl[start_pos].count; } - while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { - end_pos -= l_gl[end_pos].count; - } lines.push_back(l_gl[start_pos].start); - lines.push_back(l_gl[end_pos].end); } else { lines.push_back(line_start); - lines.push_back(range.y); } + lines.push_back(range.y); } } else { lines.push_back(0); @@ -804,6 +803,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do int prev_safe_break = 0; int last_safe_break = -1; int word_count = 0; + bool trim_next = false; int l_size = shaped_text_get_glyph_count(p_shaped); const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped); @@ -818,16 +818,15 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = prev_safe_break; int end_pos = last_safe_break; - - while ((start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { + while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { start_pos += l_gl[start_pos].count; } while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { end_pos -= l_gl[end_pos].count; } - //printf("%s", vformat("BRK TRIM(W): %d..%d -> %d..%d\n", line_start, l_gl[last_safe_break].end, l_gl[start_pos].start, l_gl[end_pos].end).utf8().get_data()); lines.push_back(l_gl[start_pos].start); lines.push_back(l_gl[end_pos].end); + trim_next = true; } else { lines.push_back(line_start); lines.push_back(l_gl[last_safe_break].end); @@ -845,16 +844,15 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = prev_safe_break; int end_pos = i; - - while ((start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { + while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { start_pos += l_gl[start_pos].count; } while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { end_pos -= l_gl[end_pos].count; } + trim_next = false; lines.push_back(l_gl[start_pos].start); lines.push_back(l_gl[end_pos].end); - //printf("%s", vformat("BRK TRIM(M): %d..%d -> %d..%d\n", line_start, l_gl[i].end, l_gl[start_pos].start, l_gl[end_pos].end).utf8().get_data()); } else { lines.push_back(line_start); lines.push_back(l_gl[i].end); @@ -887,19 +885,14 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) { int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1; int end_pos = l_size - 1; - - while ((start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { + while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { start_pos += l_gl[start_pos].count; } - while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { - end_pos -= l_gl[end_pos].count; - } lines.push_back(l_gl[start_pos].start); - lines.push_back(l_gl[end_pos].end); } else { lines.push_back(line_start); - lines.push_back(range.y); } + lines.push_back(range.y); } } else { lines.push_back(0); diff --git a/servers/text_server.h b/servers/text_server.h index e8945dd807..b62d418fc8 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -409,13 +409,13 @@ public: virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) = 0; virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const = 0; - virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0; + virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0; virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) = 0; virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0; virtual int64_t shaped_get_span_count(const RID &p_shaped) const = 0; virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const = 0; - virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) = 0; + virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) = 0; virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range. virtual RID shaped_text_get_parent(const RID &p_shaped) const = 0; diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp index 7395cd5ad4..7024a25528 100644 --- a/servers/xr/xr_interface_extension.cpp +++ b/servers/xr/xr_interface_extension.cpp @@ -358,9 +358,5 @@ RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) { RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) { // TODO implement this, the problem is that our depth texture isn't part of our render target as it is used for 3D rendering only // but we don't have access to our render buffers from here.... - RendererSceneRenderRD * rd_scene = ?????; - ERR_FAIL_NULL_V_MSG(rd_scene, RID(), "Renderer scene render not setup"); - - return rd_scene->render_buffers_get_depth_texture(????????????); } */ |