diff options
Diffstat (limited to 'servers')
50 files changed, 1255 insertions, 2373 deletions
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp index 2123fe8548..7b0151b9c1 100644 --- a/servers/audio/effects/audio_effect_pitch_shift.cpp +++ b/servers/audio/effects/audio_effect_pitch_shift.cpp @@ -326,12 +326,12 @@ int AudioEffectPitchShift::get_oversampling() const { return oversampling; } -void AudioEffectPitchShift::set_fft_size(FFT_Size p_fft_size) { +void AudioEffectPitchShift::set_fft_size(FFTSize p_fft_size) { ERR_FAIL_INDEX(p_fft_size, FFT_SIZE_MAX); fft_size = p_fft_size; } -AudioEffectPitchShift::FFT_Size AudioEffectPitchShift::get_fft_size() const { +AudioEffectPitchShift::FFTSize AudioEffectPitchShift::get_fft_size() const { return fft_size; } diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h index 18a9c33968..669943fa43 100644 --- a/servers/audio/effects/audio_effect_pitch_shift.h +++ b/servers/audio/effects/audio_effect_pitch_shift.h @@ -89,7 +89,7 @@ class AudioEffectPitchShift : public AudioEffect { public: friend class AudioEffectPitchShiftInstance; - enum FFT_Size { + enum FFTSize { FFT_SIZE_256, FFT_SIZE_512, FFT_SIZE_1024, @@ -100,7 +100,7 @@ public: float pitch_scale; int oversampling; - FFT_Size fft_size; + FFTSize fft_size; float wet; float dry; bool filter; @@ -117,12 +117,12 @@ public: void set_oversampling(int p_oversampling); int get_oversampling() const; - void set_fft_size(FFT_Size); - FFT_Size get_fft_size() const; + void set_fft_size(FFTSize); + FFTSize get_fft_size() const; AudioEffectPitchShift(); }; -VARIANT_ENUM_CAST(AudioEffectPitchShift::FFT_Size); +VARIANT_ENUM_CAST(AudioEffectPitchShift::FFTSize); #endif // AUDIO_EFFECT_PITCH_SHIFT_H diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp index 3f7ab74a74..44b7f64d52 100644 --- a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp +++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp @@ -245,12 +245,12 @@ float AudioEffectSpectrumAnalyzer::get_tap_back_pos() const { return tapback_pos; } -void AudioEffectSpectrumAnalyzer::set_fft_size(FFT_Size p_fft_size) { +void AudioEffectSpectrumAnalyzer::set_fft_size(FFTSize p_fft_size) { ERR_FAIL_INDEX(p_fft_size, FFT_SIZE_MAX); fft_size = p_fft_size; } -AudioEffectSpectrumAnalyzer::FFT_Size AudioEffectSpectrumAnalyzer::get_fft_size() const { +AudioEffectSpectrumAnalyzer::FFTSize AudioEffectSpectrumAnalyzer::get_fft_size() const { return fft_size; } diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.h b/servers/audio/effects/audio_effect_spectrum_analyzer.h index fba276e2bb..fc275446f0 100644 --- a/servers/audio/effects/audio_effect_spectrum_analyzer.h +++ b/servers/audio/effects/audio_effect_spectrum_analyzer.h @@ -71,7 +71,7 @@ class AudioEffectSpectrumAnalyzer : public AudioEffect { GDCLASS(AudioEffectSpectrumAnalyzer, AudioEffect); public: - enum FFT_Size { + enum FFTSize { FFT_SIZE_256, FFT_SIZE_512, FFT_SIZE_1024, @@ -84,7 +84,7 @@ public: friend class AudioEffectSpectrumAnalyzerInstance; float buffer_length; float tapback_pos; - FFT_Size fft_size; + FFTSize fft_size; protected: static void _bind_methods(); @@ -96,12 +96,12 @@ public: void set_tap_back_pos(float p_seconds); float get_tap_back_pos() const; - void set_fft_size(FFT_Size); - FFT_Size get_fft_size() const; + void set_fft_size(FFTSize); + FFTSize get_fft_size() const; AudioEffectSpectrumAnalyzer(); }; -VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzer::FFT_Size); +VARIANT_ENUM_CAST(AudioEffectSpectrumAnalyzer::FFTSize); #endif // AUDIO_EFFECT_SPECTRUM_ANALYZER_H diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 2fa333cc05..7bd1075006 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -253,27 +253,6 @@ bool DisplayServer::get_swap_cancel_ok() { void DisplayServer::enable_for_stealing_focus(OS::ProcessID pid) { } -//plays video natively, in fullscreen, only implemented in mobile for now, likely not possible to implement on linux also. -Error DisplayServer::native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track, int p_screen) { - ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Native video not supported by this display server."); -} - -bool DisplayServer::native_video_is_playing() const { - return false; -} - -void DisplayServer::native_video_pause() { - WARN_PRINT("Native video not supported by this display server."); -} - -void DisplayServer::native_video_unpause() { - WARN_PRINT("Native video not supported by this display server."); -} - -void DisplayServer::native_video_stop() { - WARN_PRINT("Native video not supported by this display server."); -} - Error DisplayServer::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) { WARN_PRINT("Native dialogs not supported by this display server."); return OK; @@ -477,12 +456,6 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("enable_for_stealing_focus", "process_id"), &DisplayServer::enable_for_stealing_focus); - ClassDB::bind_method(D_METHOD("native_video_play", "path", "volume", "audio_track", "subtitle_track", "screen"), &DisplayServer::native_video_play); - ClassDB::bind_method(D_METHOD("native_video_is_playing"), &DisplayServer::native_video_is_playing); - ClassDB::bind_method(D_METHOD("native_video_stop"), &DisplayServer::native_video_stop); - ClassDB::bind_method(D_METHOD("native_video_pause"), &DisplayServer::native_video_pause); - ClassDB::bind_method(D_METHOD("native_video_unpause"), &DisplayServer::native_video_unpause); - ClassDB::bind_method(D_METHOD("dialog_show", "title", "description", "buttons", "callback"), &DisplayServer::dialog_show); ClassDB::bind_method(D_METHOD("dialog_input_text", "title", "description", "existing_text", "callback"), &DisplayServer::dialog_input_text); @@ -518,7 +491,6 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_VIRTUAL_KEYBOARD); BIND_ENUM_CONSTANT(FEATURE_CURSOR_SHAPE); BIND_ENUM_CONSTANT(FEATURE_CUSTOM_CURSOR_SHAPE); - BIND_ENUM_CONSTANT(FEATURE_NATIVE_VIDEO); BIND_ENUM_CONSTANT(FEATURE_NATIVE_DIALOG); BIND_ENUM_CONSTANT(FEATURE_CONSOLE_WINDOW); BIND_ENUM_CONSTANT(FEATURE_IME); diff --git a/servers/display_server.h b/servers/display_server.h index 3aab572120..f05aa1f59a 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -97,7 +97,6 @@ public: FEATURE_VIRTUAL_KEYBOARD, FEATURE_CURSOR_SHAPE, FEATURE_CUSTOM_CURSOR_SHAPE, - FEATURE_NATIVE_VIDEO, FEATURE_NATIVE_DIALOG, FEATURE_CONSOLE_WINDOW, FEATURE_IME, @@ -324,13 +323,6 @@ public: virtual void enable_for_stealing_focus(OS::ProcessID pid); - //plays video natively, in fullscreen, only implemented in mobile for now, likely not possible to implement on linux also. - virtual Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track, int p_screen = SCREEN_OF_MAIN_WINDOW); - virtual bool native_video_is_playing() const; - virtual void native_video_pause(); - virtual void native_video_unpause(); - virtual void native_video_stop(); - virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback); virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback); diff --git a/servers/physics_2d/broad_phase_2d_basic.cpp b/servers/physics_2d/broad_phase_2d_basic.cpp deleted file mode 100644 index 17424629a9..0000000000 --- a/servers/physics_2d/broad_phase_2d_basic.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/*************************************************************************/ -/* broad_phase_2d_basic.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "broad_phase_2d_basic.h" - -BroadPhase2DBasic::ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) { - current++; - - Element e; - e.owner = p_object_; - e._static = false; - e.subindex = p_subindex; - - element_map[current] = e; - return current; -} - -void BroadPhase2DBasic::move(ID p_id, const Rect2 &p_aabb) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - E->get().aabb = p_aabb; -} - -void BroadPhase2DBasic::set_static(ID p_id, bool p_static) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - E->get()._static = p_static; -} - -void BroadPhase2DBasic::remove(ID p_id) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - element_map.erase(E); -} - -CollisionObject2DSW *BroadPhase2DBasic::get_object(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, nullptr); - return E->get().owner; -} - -bool BroadPhase2DBasic::is_static(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, false); - return E->get()._static; -} - -int BroadPhase2DBasic::get_subindex(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, -1); - return E->get().subindex; -} - -int BroadPhase2DBasic::cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { - int rc = 0; - - for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) { - const Rect2 aabb = E->get().aabb; - if (aabb.intersects_segment(p_from, p_to)) { - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) { - break; - } - } - } - - return rc; -} - -int BroadPhase2DBasic::cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { - int rc = 0; - - for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) { - const Rect2 aabb = E->get().aabb; - if (aabb.intersects(p_aabb)) { - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) { - break; - } - } - } - - return rc; -} - -void BroadPhase2DBasic::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { - pair_userdata = p_userdata; - pair_callback = p_pair_callback; -} - -void BroadPhase2DBasic::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { - unpair_userdata = p_userdata; - unpair_callback = p_unpair_callback; -} - -void BroadPhase2DBasic::update() { - // recompute pairs - for (Map<ID, Element>::Element *I = element_map.front(); I; I = I->next()) { - for (Map<ID, Element>::Element *J = I->next(); J; J = J->next()) { - Element *elem_A = &I->get(); - Element *elem_B = &J->get(); - - if (elem_A->owner == elem_B->owner) { - continue; - } - - bool pair_ok = elem_A->aabb.intersects(elem_B->aabb) && (!elem_A->_static || !elem_B->_static); - - PairKey key(I->key(), J->key()); - - Map<PairKey, void *>::Element *E = pair_map.find(key); - - if (!pair_ok && E) { - if (unpair_callback) { - unpair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, E->get(), unpair_userdata); - } - pair_map.erase(key); - } - - if (pair_ok && !E) { - void *data = nullptr; - if (pair_callback) { - data = pair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, unpair_userdata); - if (data) { - pair_map.insert(key, data); - } - } - } - } - } -} - -BroadPhase2DSW *BroadPhase2DBasic::_create() { - return memnew(BroadPhase2DBasic); -} - -BroadPhase2DBasic::BroadPhase2DBasic() { - current = 1; - unpair_callback = nullptr; - unpair_userdata = nullptr; - pair_callback = nullptr; - pair_userdata = nullptr; -} diff --git a/servers/physics_2d/broad_phase_2d_bvh.cpp b/servers/physics_2d/broad_phase_2d_bvh.cpp new file mode 100644 index 0000000000..5f53f4a012 --- /dev/null +++ b/servers/physics_2d/broad_phase_2d_bvh.cpp @@ -0,0 +1,116 @@ +/*************************************************************************/ +/* broad_phase_2d_bvh.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 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 "broad_phase_2d_bvh.h" +#include "collision_object_2d_sw.h" + +BroadPhase2DSW::ID BroadPhase2DBVH::create(CollisionObject2DSW *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) { + ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care? + return oid + 1; +} + +void BroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) { + bvh.move(p_id - 1, p_aabb); +} + +void BroadPhase2DBVH::set_static(ID p_id, bool p_static) { + CollisionObject2DSW *it = bvh.get(p_id - 1); + bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care? +} + +void BroadPhase2DBVH::remove(ID p_id) { + bvh.erase(p_id - 1); +} + +CollisionObject2DSW *BroadPhase2DBVH::get_object(ID p_id) const { + CollisionObject2DSW *it = bvh.get(p_id - 1); + ERR_FAIL_COND_V(!it, nullptr); + return it; +} + +bool BroadPhase2DBVH::is_static(ID p_id) const { + return !bvh.is_pairable(p_id - 1); +} + +int BroadPhase2DBVH::get_subindex(ID p_id) const { + return bvh.get_subindex(p_id - 1); +} + +int BroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { + return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); +} + +int BroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { + return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); +} + +void *BroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B) { + BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self); + if (!bpo->pair_callback) { + return nullptr; + } + + return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata); +} + +void BroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B, void *pairdata) { + BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self); + if (!bpo->unpair_callback) { + return; + } + + bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata); +} + +void BroadPhase2DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { + pair_callback = p_pair_callback; + pair_userdata = p_userdata; +} + +void BroadPhase2DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { + unpair_callback = p_unpair_callback; + unpair_userdata = p_userdata; +} + +void BroadPhase2DBVH::update() { + bvh.update(); +} + +BroadPhase2DSW *BroadPhase2DBVH::_create() { + return memnew(BroadPhase2DBVH); +} + +BroadPhase2DBVH::BroadPhase2DBVH() { + bvh.set_pair_callback(_pair_callback, this); + bvh.set_unpair_callback(_unpair_callback, this); + pair_callback = nullptr; + pair_userdata = nullptr; + unpair_userdata = nullptr; +} diff --git a/servers/physics_2d/broad_phase_2d_basic.h b/servers/physics_2d/broad_phase_2d_bvh.h index ca1db360fb..6c11d2561b 100644 --- a/servers/physics_2d/broad_phase_2d_basic.h +++ b/servers/physics_2d/broad_phase_2d_bvh.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_2d_basic.h */ +/* broad_phase_2d_bvh.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,49 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BROAD_PHASE_2D_BASIC_H -#define BROAD_PHASE_2D_BASIC_H +#ifndef BROAD_PHASE_2D_BVH_H +#define BROAD_PHASE_2D_BVH_H -#include "core/templates/map.h" -#include "space_2d_sw.h" -class BroadPhase2DBasic : public BroadPhase2DSW { - struct Element { - CollisionObject2DSW *owner; - bool _static; - Rect2 aabb; - int subindex; - }; +#include "broad_phase_2d_sw.h" +#include "core/math/bvh.h" +#include "core/math/rect2.h" +#include "core/math/vector2.h" - Map<ID, Element> element_map; +class BroadPhase2DBVH : public BroadPhase2DSW { + BVH_Manager<CollisionObject2DSW, true, 128, Rect2, Vector2> bvh; - ID current; - - struct PairKey { - union { - struct { - ID a; - ID b; - }; - uint64_t key; - }; - - _FORCE_INLINE_ bool operator<(const PairKey &p_key) const { - return key < p_key.key; - } - - PairKey() { key = 0; } - PairKey(ID p_a, ID p_b) { - if (p_a > p_b) { - a = p_b; - b = p_a; - } else { - a = p_a; - b = p_b; - } - } - }; - - Map<PairKey, void *> pair_map; + static void *_pair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int); + static void _unpair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int, void *); PairCallback pair_callback; void *pair_userdata; @@ -79,7 +49,7 @@ class BroadPhase2DBasic : public BroadPhase2DSW { public: // 0 is an invalid ID - virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0); + virtual ID create(CollisionObject2DSW *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false); virtual void move(ID p_id, const Rect2 &p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); @@ -97,7 +67,7 @@ public: virtual void update(); static BroadPhase2DSW *_create(); - BroadPhase2DBasic(); + BroadPhase2DBVH(); }; -#endif // BROAD_PHASE_2D_BASIC_H +#endif // BROAD_PHASE_2D_BVH_H diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp deleted file mode 100644 index 35447c5389..0000000000 --- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp +++ /dev/null @@ -1,738 +0,0 @@ -/*************************************************************************/ -/* broad_phase_2d_hash_grid.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "broad_phase_2d_hash_grid.h" -#include "collision_object_2d_sw.h" -#include "core/config/project_settings.h" - -#define LARGE_ELEMENT_FI 1.01239812 - -void BroadPhase2DHashGrid::_pair_attempt(Element *p_elem, Element *p_with) { - if (p_elem->owner == p_with->owner) { - return; - } - if (!_test_collision_mask(p_elem->collision_mask, p_elem->collision_layer, p_with->collision_mask, p_with->collision_layer)) { - return; - } - Map<Element *, PairData *>::Element *E = p_elem->paired.find(p_with); - - ERR_FAIL_COND(p_elem->_static && p_with->_static); - - if (!E) { - PairData *pd = memnew(PairData); - p_elem->paired[p_with] = pd; - p_with->paired[p_elem] = pd; - } else { - E->get()->rc++; - } -} - -void BroadPhase2DHashGrid::_unpair_attempt(Element *p_elem, Element *p_with) { - if (p_elem->owner == p_with->owner) { - return; - } - if (!_test_collision_mask(p_elem->collision_mask, p_elem->collision_layer, p_with->collision_mask, p_with->collision_layer)) { - return; - } - Map<Element *, PairData *>::Element *E = p_elem->paired.find(p_with); - - ERR_FAIL_COND(!E); //this should really be paired.. - - E->get()->rc--; - - if (E->get()->rc == 0) { - if (E->get()->colliding) { - //uncollide - if (unpair_callback) { - unpair_callback(p_elem->owner, p_elem->subindex, p_with->owner, p_with->subindex, E->get()->ud, unpair_userdata); - } - } - - memdelete(E->get()); - p_elem->paired.erase(E); - p_with->paired.erase(p_elem); - } -} - -void BroadPhase2DHashGrid::_check_motion(Element *p_elem) { - for (Map<Element *, PairData *>::Element *E = p_elem->paired.front(); E; E = E->next()) { - bool physical_collision = p_elem->aabb.intersects(E->key()->aabb); - bool logical_collision = p_elem->owner->test_collision_mask(E->key()->owner); - - if (physical_collision && logical_collision) { - if (!E->get()->colliding && pair_callback) { - E->get()->ud = pair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, pair_userdata); - } - E->get()->colliding = true; - } else { // No collision - if (E->get()->colliding && unpair_callback) { - unpair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, E->get()->ud, unpair_userdata); - E->get()->ud = nullptr; - } - E->get()->colliding = false; - } - } -} - -void BroadPhase2DHashGrid::_enter_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_enter) { - Vector2 sz = (p_rect.size / cell_size * LARGE_ELEMENT_FI); //use magic number to avoid floating point issues - if (sz.width * sz.height > large_object_min_surface) { - //large object, do not use grid, must check against all elements - for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) { - if (E->key() == p_elem->self) { - continue; // do not pair against itself - } - if (E->get()._static && p_static) { - continue; - } - - _pair_attempt(p_elem, &E->get()); - } - - large_elements[p_elem].inc(); - return; - } - - Point2i from = (p_rect.position / cell_size).floor(); - Point2i to = ((p_rect.position + p_rect.size) / cell_size).floor(); - - for (int i = from.x; i <= to.x; i++) { - for (int j = from.y; j <= to.y; j++) { - PosKey pk; - pk.x = i; - pk.y = j; - - uint32_t idx = pk.hash() % hash_table_size; - PosBin *pb = hash_table[idx]; - - while (pb) { - if (pb->key == pk) { - break; - } - - pb = pb->next; - } - - bool entered = p_force_enter; - - if (!pb) { - //does not exist, create! - pb = memnew(PosBin); - pb->key = pk; - pb->next = hash_table[idx]; - hash_table[idx] = pb; - } - - if (p_static) { - if (pb->static_object_set[p_elem].inc() == 1) { - entered = true; - } - } else { - if (pb->object_set[p_elem].inc() == 1) { - entered = true; - } - } - - if (entered) { - for (Map<Element *, RC>::Element *E = pb->object_set.front(); E; E = E->next()) { - _pair_attempt(p_elem, E->key()); - } - - if (!p_static) { - for (Map<Element *, RC>::Element *E = pb->static_object_set.front(); E; E = E->next()) { - _pair_attempt(p_elem, E->key()); - } - } - } - } - } - - //pair separatedly with large elements - - for (Map<Element *, RC>::Element *E = large_elements.front(); E; E = E->next()) { - if (E->key() == p_elem) { - continue; // do not pair against itself - } - if (E->key()->_static && p_static) { - continue; - } - _pair_attempt(E->key(), p_elem); - } -} - -void BroadPhase2DHashGrid::_exit_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_exit) { - Vector2 sz = (p_rect.size / cell_size * LARGE_ELEMENT_FI); - if (sz.width * sz.height > large_object_min_surface) { - //unpair all elements, instead of checking all, just check what is already paired, so we at least save from checking static vs static - Map<Element *, PairData *>::Element *E = p_elem->paired.front(); - while (E) { - Map<Element *, PairData *>::Element *next = E->next(); - _unpair_attempt(p_elem, E->key()); - E = next; - } - - if (large_elements[p_elem].dec() == 0) { - large_elements.erase(p_elem); - } - return; - } - - Point2i from = (p_rect.position / cell_size).floor(); - Point2i to = ((p_rect.position + p_rect.size) / cell_size).floor(); - - for (int i = from.x; i <= to.x; i++) { - for (int j = from.y; j <= to.y; j++) { - PosKey pk; - pk.x = i; - pk.y = j; - - uint32_t idx = pk.hash() % hash_table_size; - PosBin *pb = hash_table[idx]; - - while (pb) { - if (pb->key == pk) { - break; - } - - pb = pb->next; - } - - ERR_CONTINUE(!pb); //should exist!! - - bool exited = p_force_exit; - - if (p_static) { - if (pb->static_object_set[p_elem].dec() == 0) { - pb->static_object_set.erase(p_elem); - exited = true; - } - } else { - if (pb->object_set[p_elem].dec() == 0) { - pb->object_set.erase(p_elem); - exited = true; - } - } - - if (exited) { - for (Map<Element *, RC>::Element *E = pb->object_set.front(); E; E = E->next()) { - _unpair_attempt(p_elem, E->key()); - } - - if (!p_static) { - for (Map<Element *, RC>::Element *E = pb->static_object_set.front(); E; E = E->next()) { - _unpair_attempt(p_elem, E->key()); - } - } - } - - if (pb->object_set.is_empty() && pb->static_object_set.is_empty()) { - if (hash_table[idx] == pb) { - hash_table[idx] = pb->next; - } else { - PosBin *px = hash_table[idx]; - - while (px) { - if (px->next == pb) { - px->next = pb->next; - break; - } - - px = px->next; - } - - ERR_CONTINUE(!px); - } - - memdelete(pb); - } - } - } - - for (Map<Element *, RC>::Element *E = large_elements.front(); E; E = E->next()) { - if (E->key() == p_elem) { - continue; // do not pair against itself - } - if (E->key()->_static && p_static) { - continue; - } - - //unpair from large elements - _unpair_attempt(p_elem, E->key()); - } -} - -BroadPhase2DHashGrid::ID BroadPhase2DHashGrid::create(CollisionObject2DSW *p_object, int p_subindex) { - current++; - - Element e; - e.owner = p_object; - e._static = false; - e.collision_mask = p_object->get_collision_mask(); - e.collision_layer = p_object->get_collision_layer(); - e.subindex = p_subindex; - e.self = current; - e.pass = 0; - - element_map[current] = e; - return current; -} - -void BroadPhase2DHashGrid::move(ID p_id, const Rect2 &p_aabb) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - - Element &e = E->get(); - bool layer_changed = e.collision_mask != e.owner->get_collision_mask() || e.collision_layer != e.owner->get_collision_layer(); - - if (p_aabb != e.aabb || layer_changed) { - uint32_t old_mask = e.collision_mask; - uint32_t old_layer = e.collision_layer; - if (p_aabb != Rect2()) { - e.collision_mask = e.owner->get_collision_mask(); - e.collision_layer = e.owner->get_collision_layer(); - - _enter_grid(&e, p_aabb, e._static, layer_changed); - } - if (e.aabb != Rect2()) { - // Need _exit_grid to remove from cells based on the old layer values. - e.collision_mask = old_mask; - e.collision_layer = old_layer; - - _exit_grid(&e, e.aabb, e._static, layer_changed); - - e.collision_mask = e.owner->get_collision_mask(); - e.collision_layer = e.owner->get_collision_layer(); - } - e.aabb = p_aabb; - } - - _check_motion(&e); -} - -void BroadPhase2DHashGrid::set_static(ID p_id, bool p_static) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - - Element &e = E->get(); - - if (e._static == p_static) { - return; - } - - if (e.aabb != Rect2()) { - _exit_grid(&e, e.aabb, e._static, false); - } - - e._static = p_static; - - if (e.aabb != Rect2()) { - _enter_grid(&e, e.aabb, e._static, false); - _check_motion(&e); - } -} - -void BroadPhase2DHashGrid::remove(ID p_id) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - - Element &e = E->get(); - - if (e.aabb != Rect2()) { - _exit_grid(&e, e.aabb, e._static, false); - } - - element_map.erase(p_id); -} - -CollisionObject2DSW *BroadPhase2DHashGrid::get_object(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, nullptr); - return E->get().owner; -} - -bool BroadPhase2DHashGrid::is_static(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, false); - return E->get()._static; -} - -int BroadPhase2DHashGrid::get_subindex(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, -1); - return E->get().subindex; -} - -template <bool use_aabb, bool use_segment> -void BroadPhase2DHashGrid::_cull(const Point2i p_cell, const Rect2 &p_aabb, const Point2 &p_from, const Point2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices, int &index) { - PosKey pk; - pk.x = p_cell.x; - pk.y = p_cell.y; - - uint32_t idx = pk.hash() % hash_table_size; - PosBin *pb = hash_table[idx]; - - while (pb) { - if (pb->key == pk) { - break; - } - - pb = pb->next; - } - - if (!pb) { - return; - } - - for (Map<Element *, RC>::Element *E = pb->object_set.front(); E; E = E->next()) { - if (index >= p_max_results) { - break; - } - if (E->key()->pass == pass) { - continue; - } - - E->key()->pass = pass; - - if (use_aabb && !p_aabb.intersects(E->key()->aabb)) { - continue; - } - - if (use_segment && !E->key()->aabb.intersects_segment(p_from, p_to)) { - continue; - } - - p_results[index] = E->key()->owner; - p_result_indices[index] = E->key()->subindex; - index++; - } - - for (Map<Element *, RC>::Element *E = pb->static_object_set.front(); E; E = E->next()) { - if (index >= p_max_results) { - break; - } - if (E->key()->pass == pass) { - continue; - } - - if (use_aabb && !p_aabb.intersects(E->key()->aabb)) { - continue; - } - - if (use_segment && !E->key()->aabb.intersects_segment(p_from, p_to)) { - continue; - } - - E->key()->pass = pass; - p_results[index] = E->key()->owner; - p_result_indices[index] = E->key()->subindex; - index++; - } -} - -int BroadPhase2DHashGrid::cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { - pass++; - - Vector2 dir = (p_to - p_from); - if (dir == Vector2()) { - return 0; - } - //avoid divisions by zero - dir.normalize(); - if (dir.x == 0.0) { - dir.x = 0.000001; - } - if (dir.y == 0.0) { - dir.y = 0.000001; - } - Vector2 delta = dir.abs(); - - delta.x = cell_size / delta.x; - delta.y = cell_size / delta.y; - - Point2i pos = (p_from / cell_size).floor(); - Point2i end = (p_to / cell_size).floor(); - - Point2i step = Vector2(SGN(dir.x), SGN(dir.y)); - - Vector2 max; - - if (dir.x < 0) { - max.x = (Math::floor((double)pos.x) * cell_size - p_from.x) / dir.x; - } else { - max.x = (Math::floor((double)pos.x + 1) * cell_size - p_from.x) / dir.x; - } - - if (dir.y < 0) { - max.y = (Math::floor((double)pos.y) * cell_size - p_from.y) / dir.y; - } else { - max.y = (Math::floor((double)pos.y + 1) * cell_size - p_from.y) / dir.y; - } - - int cullcount = 0; - _cull<false, true>(pos, Rect2(), p_from, p_to, p_results, p_max_results, p_result_indices, cullcount); - - bool reached_x = false; - bool reached_y = false; - - while (true) { - if (max.x < max.y) { - max.x += delta.x; - pos.x += step.x; - } else { - max.y += delta.y; - pos.y += step.y; - } - - if (step.x > 0) { - if (pos.x >= end.x) { - reached_x = true; - } - } else if (pos.x <= end.x) { - reached_x = true; - } - - if (step.y > 0) { - if (pos.y >= end.y) { - reached_y = true; - } - } else if (pos.y <= end.y) { - reached_y = true; - } - - _cull<false, true>(pos, Rect2(), p_from, p_to, p_results, p_max_results, p_result_indices, cullcount); - - if (reached_x && reached_y) { - break; - } - } - - for (Map<Element *, RC>::Element *E = large_elements.front(); E; E = E->next()) { - if (cullcount >= p_max_results) { - break; - } - if (E->key()->pass == pass) { - continue; - } - - E->key()->pass = pass; - - /* - if (use_aabb && !p_aabb.intersects(E->key()->aabb)) - continue; - */ - - if (!E->key()->aabb.intersects_segment(p_from, p_to)) { - continue; - } - - p_results[cullcount] = E->key()->owner; - p_result_indices[cullcount] = E->key()->subindex; - cullcount++; - } - - return cullcount; -} - -int BroadPhase2DHashGrid::cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { - pass++; - - Point2i from = (p_aabb.position / cell_size).floor(); - Point2i to = ((p_aabb.position + p_aabb.size) / cell_size).floor(); - int cullcount = 0; - - for (int i = from.x; i <= to.x; i++) { - for (int j = from.y; j <= to.y; j++) { - _cull<true, false>(Point2i(i, j), p_aabb, Point2(), Point2(), p_results, p_max_results, p_result_indices, cullcount); - } - } - - for (Map<Element *, RC>::Element *E = large_elements.front(); E; E = E->next()) { - if (cullcount >= p_max_results) { - break; - } - if (E->key()->pass == pass) { - continue; - } - - E->key()->pass = pass; - - if (!p_aabb.intersects(E->key()->aabb)) { - continue; - } - - /* - if (!E->key()->aabb.intersects_segment(p_from,p_to)) - continue; - */ - - p_results[cullcount] = E->key()->owner; - p_result_indices[cullcount] = E->key()->subindex; - cullcount++; - } - return cullcount; -} - -void BroadPhase2DHashGrid::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { - pair_callback = p_pair_callback; - pair_userdata = p_userdata; -} - -void BroadPhase2DHashGrid::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { - unpair_callback = p_unpair_callback; - unpair_userdata = p_userdata; -} - -void BroadPhase2DHashGrid::update() { -} - -BroadPhase2DSW *BroadPhase2DHashGrid::_create() { - return memnew(BroadPhase2DHashGrid); -} - -BroadPhase2DHashGrid::BroadPhase2DHashGrid() { - hash_table_size = GLOBAL_DEF("physics/2d/bp_hash_table_size", 4096); - ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/bp_hash_table_size", PropertyInfo(Variant::INT, "physics/2d/bp_hash_table_size", PROPERTY_HINT_RANGE, "0,8192,1,or_greater")); - hash_table_size = Math::larger_prime(hash_table_size); - hash_table = memnew_arr(PosBin *, hash_table_size); - - cell_size = GLOBAL_DEF("physics/2d/cell_size", 128); - ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/cell_size", PropertyInfo(Variant::INT, "physics/2d/cell_size", PROPERTY_HINT_RANGE, "0,512,1,or_greater")); - - large_object_min_surface = GLOBAL_DEF("physics/2d/large_object_surface_threshold_in_cells", 512); - ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/large_object_surface_threshold_in_cells", PropertyInfo(Variant::INT, "physics/2d/large_object_surface_threshold_in_cells", PROPERTY_HINT_RANGE, "0,1024,1,or_greater")); - - for (uint32_t i = 0; i < hash_table_size; i++) { - hash_table[i] = nullptr; - } - pass = 1; - - current = 0; -} - -BroadPhase2DHashGrid::~BroadPhase2DHashGrid() { - for (uint32_t i = 0; i < hash_table_size; i++) { - while (hash_table[i]) { - PosBin *pb = hash_table[i]; - hash_table[i] = pb->next; - memdelete(pb); - } - } - - memdelete_arr(hash_table); -} - -/* 3D version of voxel traversal: - -public IEnumerable<Point3D> GetCellsOnRay(Ray ray, int maxDepth) -{ - // Implementation is based on: - // "A Fast Voxel Traversal Algorithm for Ray Tracing" - // John Amanatides, Andrew Woo - // http://www.cse.yorku.ca/~amana/research/grid.pdf - // https://web.archive.org/web/20100616193049/http://www.devmaster.net/articles/raytracing_series/A%20faster%20voxel%20traversal%20algorithm%20for%20ray%20tracing.pdf - - // NOTES: - // * This code assumes that the ray's position and direction are in 'cell coordinates', which means - // that one unit equals one cell in all directions. - // * When the ray doesn't start within the voxel grid, calculate the first position at which the - // ray could enter the grid. If it never enters the grid, there is nothing more to do here. - // * Also, it is important to test when the ray exits the voxel grid when the grid isn't infinite. - // * The Point3D structure is a simple structure having three integer fields (X, Y and Z). - - // The cell in which the ray starts. - Point3D start = GetCellAt(ray.Position); // Rounds the position's X, Y and Z down to the nearest integer values. - int x = start.X; - int y = start.Y; - int z = start.Z; - - // Determine which way we go. - int stepX = Math.Sign(ray.Direction.X); - int stepY = Math.Sign(ray.Direction.Y); - int stepZ = Math.Sign(ray.Direction.Z); - - // Calculate cell boundaries. When the step (i.e. direction sign) is positive, - // the next boundary is AFTER our current position, meaning that we have to add 1. - // Otherwise, it is BEFORE our current position, in which case we add nothing. - Point3D cellBoundary = new Point3D( - x + (stepX > 0 ? 1 : 0), - y + (stepY > 0 ? 1 : 0), - z + (stepZ > 0 ? 1 : 0)); - - // NOTE: For the following calculations, the result will be Single.PositiveInfinity - // when ray.Direction.X, Y or Z equals zero, which is OK. However, when the left-hand - // value of the division also equals zero, the result is Single.NaN, which is not OK. - - // Determine how far we can travel along the ray before we hit a voxel boundary. - Vector3 tMax = new Vector3( - (cellBoundary.X - ray.Position.X) / ray.Direction.X, // Boundary is a plane on the YZ axis. - (cellBoundary.Y - ray.Position.Y) / ray.Direction.Y, // Boundary is a plane on the XZ axis. - (cellBoundary.Z - ray.Position.Z) / ray.Direction.Z); // Boundary is a plane on the XY axis. - if (Single.IsNaN(tMax.X)) tMax.X = Single.PositiveInfinity; - if (Single.IsNaN(tMax.Y)) tMax.Y = Single.PositiveInfinity; - if (Single.IsNaN(tMax.Z)) tMax.Z = Single.PositiveInfinity; - - // Determine how far we must travel along the ray before we have crossed a gridcell. - Vector3 tDelta = new Vector3( - stepX / ray.Direction.X, // Crossing the width of a cell. - stepY / ray.Direction.Y, // Crossing the height of a cell. - stepZ / ray.Direction.Z); // Crossing the depth of a cell. - if (Single.IsNaN(tDelta.X)) tDelta.X = Single.PositiveInfinity; - if (Single.IsNaN(tDelta.Y)) tDelta.Y = Single.PositiveInfinity; - if (Single.IsNaN(tDelta.Z)) tDelta.Z = Single.PositiveInfinity; - - // For each step, determine which distance to the next voxel boundary is lowest (i.e. - // which voxel boundary is nearest) and walk that way. - for (int i = 0; i < maxDepth; i++) - { - // Return it. - yield return new Point3D(x, y, z); - - // Do the next step. - if (tMax.X < tMax.Y && tMax.X < tMax.Z) - { - // tMax.X is the lowest, an YZ cell boundary plane is nearest. - x += stepX; - tMax.X += tDelta.X; - } - else if (tMax.Y < tMax.Z) - { - // tMax.Y is the lowest, an XZ cell boundary plane is nearest. - y += stepY; - tMax.Y += tDelta.Y; - } - else - { - // tMax.Z is the lowest, an XY cell boundary plane is nearest. - z += stepZ; - tMax.Z += tDelta.Z; - } - } - - */ diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.h b/servers/physics_2d/broad_phase_2d_hash_grid.h deleted file mode 100644 index bb7c03b989..0000000000 --- a/servers/physics_2d/broad_phase_2d_hash_grid.h +++ /dev/null @@ -1,194 +0,0 @@ -/*************************************************************************/ -/* broad_phase_2d_hash_grid.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 BROAD_PHASE_2D_HASH_GRID_H -#define BROAD_PHASE_2D_HASH_GRID_H - -#include "broad_phase_2d_sw.h" -#include "core/templates/map.h" - -class BroadPhase2DHashGrid : public BroadPhase2DSW { - struct PairData { - bool colliding; - int rc; - void *ud; - PairData() { - colliding = false; - rc = 1; - ud = nullptr; - } - }; - - struct Element { - ID self; - CollisionObject2DSW *owner; - bool _static; - Rect2 aabb; - // Owner's collision_mask/layer, used to detect changes in layers. - uint32_t collision_mask; - uint32_t collision_layer; - int subindex; - uint64_t pass; - Map<Element *, PairData *> paired; - }; - - struct RC { - int ref; - - _FORCE_INLINE_ int inc() { - ref++; - return ref; - } - _FORCE_INLINE_ int dec() { - ref--; - return ref; - } - - _FORCE_INLINE_ RC() { - ref = 0; - } - }; - - Map<ID, Element> element_map; - Map<Element *, RC> large_elements; - - ID current; - - uint64_t pass; - - struct PairKey { - union { - struct { - ID a; - ID b; - }; - uint64_t key; - }; - - _FORCE_INLINE_ bool operator<(const PairKey &p_key) const { - return key < p_key.key; - } - - PairKey() { key = 0; } - PairKey(ID p_a, ID p_b) { - if (p_a > p_b) { - a = p_b; - b = p_a; - } else { - a = p_a; - b = p_b; - } - } - }; - - Map<PairKey, PairData> pair_map; - - int cell_size; - int large_object_min_surface; - - PairCallback pair_callback; - void *pair_userdata; - UnpairCallback unpair_callback; - void *unpair_userdata; - - static _FORCE_INLINE_ bool _test_collision_mask(uint32_t p_mask1, uint32_t p_layer1, uint32_t p_mask2, uint32_t p_layer2) { - return p_mask1 & p_layer2 || p_mask2 & p_layer1; - } - - void _enter_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_enter); - void _exit_grid(Element *p_elem, const Rect2 &p_rect, bool p_static, bool p_force_exit); - template <bool use_aabb, bool use_segment> - _FORCE_INLINE_ void _cull(const Point2i p_cell, const Rect2 &p_aabb, const Point2 &p_from, const Point2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices, int &index); - - struct PosKey { - union { - struct { - int32_t x; - int32_t y; - }; - uint64_t key; - }; - - _FORCE_INLINE_ uint32_t hash() const { - uint64_t k = key; - k = (~k) + (k << 18); // k = (k << 18) - k - 1; - k = k ^ (k >> 31); - k = k * 21; // k = (k + (k << 2)) + (k << 4); - k = k ^ (k >> 11); - k = k + (k << 6); - k = k ^ (k >> 22); - return k; - } - - bool operator==(const PosKey &p_key) const { return key == p_key.key; } - _FORCE_INLINE_ bool operator<(const PosKey &p_key) const { - return key < p_key.key; - } - }; - - struct PosBin { - PosKey key; - Map<Element *, RC> object_set; - Map<Element *, RC> static_object_set; - PosBin *next; - }; - - uint32_t hash_table_size; - PosBin **hash_table; - - void _pair_attempt(Element *p_elem, Element *p_with); - void _unpair_attempt(Element *p_elem, Element *p_with); - void _check_motion(Element *p_elem); - -public: - virtual ID create(CollisionObject2DSW *p_object, int p_subindex = 0); - virtual void move(ID p_id, const Rect2 &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); - - virtual CollisionObject2DSW *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; - - virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); - - virtual void update(); - - static BroadPhase2DSW *_create(); - - BroadPhase2DHashGrid(); - ~BroadPhase2DHashGrid(); -}; - -#endif // BROAD_PHASE_2D_HASH_GRID_H diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/broad_phase_2d_sw.h index d17ee6e2d6..0f82f06b9c 100644 --- a/servers/physics_2d/broad_phase_2d_sw.h +++ b/servers/physics_2d/broad_phase_2d_sw.h @@ -48,7 +48,7 @@ public: typedef void (*UnpairCallback)(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_userdata); // 0 is an invalid ID - virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0) = 0; + virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) = 0; virtual void move(ID p_id, const Rect2 &p_aabb) = 0; virtual void set_static(ID p_id, bool p_static) = 0; virtual void remove(ID p_id) = 0; diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 7a2f312263..fa87dc1f3f 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -182,19 +182,19 @@ void CollisionObject2DSW::_update_shapes() { continue; } - if (s.bpid == 0) { - s.bpid = space->get_broadphase()->create(this, i); - space->get_broadphase()->set_static(s.bpid, _static); - } - //not quite correct, should compute the next matrix.. Rect2 shape_aabb = s.shape->get_aabb(); Transform2D xform = transform * s.xform; shape_aabb = xform.xform(shape_aabb); + shape_aabb.grow_by((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05); s.aabb_cache = shape_aabb; - s.aabb_cache = s.aabb_cache.grow((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05); - space->get_broadphase()->move(s.bpid, s.aabb_cache); + if (s.bpid == 0) { + s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static); + space->get_broadphase()->set_static(s.bpid, _static); + } + + space->get_broadphase()->move(s.bpid, shape_aabb); } } @@ -209,11 +209,6 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) { continue; } - if (s.bpid == 0) { - s.bpid = space->get_broadphase()->create(this, i); - space->get_broadphase()->set_static(s.bpid, _static); - } - //not quite correct, should compute the next matrix.. Rect2 shape_aabb = s.shape->get_aabb(); Transform2D xform = transform * s.xform; @@ -221,6 +216,11 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) { shape_aabb = shape_aabb.merge(Rect2(shape_aabb.position + p_motion, shape_aabb.size)); //use motion s.aabb_cache = shape_aabb; + if (s.bpid == 0) { + s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static); + space->get_broadphase()->set_static(s.bpid, _static); + } + space->get_broadphase()->move(s.bpid, shape_aabb); } } diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 6d64f4126c..425546e5ca 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -30,8 +30,7 @@ #include "physics_server_2d_sw.h" -#include "broad_phase_2d_basic.h" -#include "broad_phase_2d_hash_grid.h" +#include "broad_phase_2d_bvh.h" #include "collision_solver_2d_sw.h" #include "core/config/project_settings.h" #include "core/debugger/engine_debugger.h" @@ -1356,8 +1355,7 @@ PhysicsServer2DSW *PhysicsServer2DSW::singletonsw = nullptr; PhysicsServer2DSW::PhysicsServer2DSW(bool p_using_threads) { singletonsw = this; - BroadPhase2DSW::create_func = BroadPhase2DHashGrid::_create; - //BroadPhase2DSW::create_func=BroadPhase2DBasic::_create; + BroadPhase2DSW::create_func = BroadPhase2DBVH::_create; active = true; island_count = 0; diff --git a/servers/physics_3d/broad_phase_3d_basic.cpp b/servers/physics_3d/broad_phase_3d_basic.cpp deleted file mode 100644 index b41c2530da..0000000000 --- a/servers/physics_3d/broad_phase_3d_basic.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/*************************************************************************/ -/* broad_phase_3d_basic.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 "broad_phase_3d_basic.h" -#include "core/string/print_string.h" -#include "core/templates/list.h" - -BroadPhase3DSW::ID BroadPhase3DBasic::create(CollisionObject3DSW *p_object, int p_subindex) { - ERR_FAIL_COND_V(p_object == nullptr, 0); - - current++; - - Element e; - e.owner = p_object; - e._static = false; - e.subindex = p_subindex; - - element_map[current] = e; - return current; -} - -void BroadPhase3DBasic::move(ID p_id, const AABB &p_aabb) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - E->get().aabb = p_aabb; -} - -void BroadPhase3DBasic::set_static(ID p_id, bool p_static) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - E->get()._static = p_static; -} - -void BroadPhase3DBasic::remove(ID p_id) { - Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - List<PairKey> to_erase; - //unpair must be done immediately on removal to avoid potential invalid pointers - for (Map<PairKey, void *>::Element *F = pair_map.front(); F; F = F->next()) { - if (F->key().a == p_id || F->key().b == p_id) { - if (unpair_callback) { - Element *elem_A = &element_map[F->key().a]; - Element *elem_B = &element_map[F->key().b]; - unpair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, F->get(), unpair_userdata); - } - to_erase.push_back(F->key()); - } - } - while (to_erase.size()) { - pair_map.erase(to_erase.front()->get()); - to_erase.pop_front(); - } - element_map.erase(E); -} - -CollisionObject3DSW *BroadPhase3DBasic::get_object(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, nullptr); - return E->get().owner; -} - -bool BroadPhase3DBasic::is_static(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, false); - return E->get()._static; -} - -int BroadPhase3DBasic::get_subindex(ID p_id) const { - const Map<ID, Element>::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, -1); - return E->get().subindex; -} - -int BroadPhase3DBasic::cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { - int rc = 0; - - for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) { - const AABB aabb = E->get().aabb; - if (aabb.has_point(p_point)) { - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) { - break; - } - } - } - - return rc; -} - -int BroadPhase3DBasic::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { - int rc = 0; - - for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) { - const AABB aabb = E->get().aabb; - if (aabb.intersects_segment(p_from, p_to)) { - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) { - break; - } - } - } - - return rc; -} - -int BroadPhase3DBasic::cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { - int rc = 0; - - for (Map<ID, Element>::Element *E = element_map.front(); E; E = E->next()) { - const AABB aabb = E->get().aabb; - if (aabb.intersects(p_aabb)) { - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) { - break; - } - } - } - - return rc; -} - -void BroadPhase3DBasic::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { - pair_userdata = p_userdata; - pair_callback = p_pair_callback; -} - -void BroadPhase3DBasic::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { - unpair_userdata = p_userdata; - unpair_callback = p_unpair_callback; -} - -void BroadPhase3DBasic::update() { - // recompute pairs - for (Map<ID, Element>::Element *I = element_map.front(); I; I = I->next()) { - for (Map<ID, Element>::Element *J = I->next(); J; J = J->next()) { - Element *elem_A = &I->get(); - Element *elem_B = &J->get(); - - if (elem_A->owner == elem_B->owner) { - continue; - } - - bool pair_ok = elem_A->aabb.intersects(elem_B->aabb) && (!elem_A->_static || !elem_B->_static); - - PairKey key(I->key(), J->key()); - - Map<PairKey, void *>::Element *E = pair_map.find(key); - - if (!pair_ok && E) { - if (unpair_callback) { - unpair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, E->get(), unpair_userdata); - } - pair_map.erase(key); - } - - if (pair_ok && !E) { - void *data = nullptr; - if (pair_callback) { - data = pair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, unpair_userdata); - if (data) { - pair_map.insert(key, data); - } - } - } - } - } -} - -BroadPhase3DSW *BroadPhase3DBasic::_create() { - return memnew(BroadPhase3DBasic); -} - -BroadPhase3DBasic::BroadPhase3DBasic() { - current = 1; - unpair_callback = nullptr; - unpair_userdata = nullptr; - pair_callback = nullptr; - pair_userdata = nullptr; -} diff --git a/servers/physics_3d/broad_phase_3d_basic.h b/servers/physics_3d/broad_phase_3d_basic.h deleted file mode 100644 index 54d34e005f..0000000000 --- a/servers/physics_3d/broad_phase_3d_basic.h +++ /dev/null @@ -1,105 +0,0 @@ -/*************************************************************************/ -/* broad_phase_3d_basic.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 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 BROAD_PHASE_BASIC_H -#define BROAD_PHASE_BASIC_H - -#include "broad_phase_3d_sw.h" -#include "core/templates/map.h" - -class BroadPhase3DBasic : public BroadPhase3DSW { - struct Element { - CollisionObject3DSW *owner; - bool _static; - AABB aabb; - int subindex; - }; - - Map<ID, Element> element_map; - - ID current; - - struct PairKey { - union { - struct { - ID a; - ID b; - }; - uint64_t key; - }; - - _FORCE_INLINE_ bool operator<(const PairKey &p_key) const { - return key < p_key.key; - } - - PairKey() { key = 0; } - PairKey(ID p_a, ID p_b) { - if (p_a > p_b) { - a = p_b; - b = p_a; - } else { - a = p_a; - b = p_b; - } - } - }; - - Map<PairKey, void *> pair_map; - - PairCallback pair_callback; - void *pair_userdata; - UnpairCallback unpair_callback; - void *unpair_userdata; - -public: - // 0 is an invalid ID - virtual ID create(CollisionObject3DSW *p_object, int p_subindex = 0); - virtual void move(ID p_id, const AABB &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); - - virtual CollisionObject3DSW *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; - - virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); - - virtual void update(); - - static BroadPhase3DSW *_create(); - BroadPhase3DBasic(); -}; - -#endif // BROAD_PHASE_BASIC_H diff --git a/servers/physics_3d/broad_phase_octree.cpp b/servers/physics_3d/broad_phase_3d_bvh.cpp index 11324fa4e4..f9f64f786d 100644 --- a/servers/physics_3d/broad_phase_octree.cpp +++ b/servers/physics_3d/broad_phase_3d_bvh.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_octree.cpp */ +/* broad_phase_3d_bvh.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,55 +28,55 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "broad_phase_octree.h" +#include "broad_phase_3d_bvh.h" #include "collision_object_3d_sw.h" -BroadPhase3DSW::ID BroadPhaseOctree::create(CollisionObject3DSW *p_object, int p_subindex) { - ID oid = octree.create(p_object, AABB(), p_subindex, false, 1 << p_object->get_type(), 0); - return oid; +BroadPhase3DBVH::ID BroadPhase3DBVH::create(CollisionObject3DSW *p_object, int p_subindex, const AABB &p_aabb, bool p_static) { + ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care? + return oid + 1; } -void BroadPhaseOctree::move(ID p_id, const AABB &p_aabb) { - octree.move(p_id, p_aabb); +void BroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) { + bvh.move(p_id - 1, p_aabb); } -void BroadPhaseOctree::set_static(ID p_id, bool p_static) { - CollisionObject3DSW *it = octree.get(p_id); - octree.set_pairable(p_id, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF); //pair everything, don't care 1? +void BroadPhase3DBVH::set_static(ID p_id, bool p_static) { + CollisionObject3DSW *it = bvh.get(p_id - 1); + bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care? } -void BroadPhaseOctree::remove(ID p_id) { - octree.erase(p_id); +void BroadPhase3DBVH::remove(ID p_id) { + bvh.erase(p_id - 1); } -CollisionObject3DSW *BroadPhaseOctree::get_object(ID p_id) const { - CollisionObject3DSW *it = octree.get(p_id); +CollisionObject3DSW *BroadPhase3DBVH::get_object(ID p_id) const { + CollisionObject3DSW *it = bvh.get(p_id - 1); ERR_FAIL_COND_V(!it, nullptr); return it; } -bool BroadPhaseOctree::is_static(ID p_id) const { - return !octree.is_pairable(p_id); +bool BroadPhase3DBVH::is_static(ID p_id) const { + return !bvh.is_pairable(p_id - 1); } -int BroadPhaseOctree::get_subindex(ID p_id) const { - return octree.get_subindex(p_id); +int BroadPhase3DBVH::get_subindex(ID p_id) const { + return bvh.get_subindex(p_id - 1); } -int BroadPhaseOctree::cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { - return octree.cull_point(p_point, p_results, p_max_results, p_result_indices); +int BroadPhase3DBVH::cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + return bvh.cull_point(p_point, p_results, p_max_results, p_result_indices); } -int BroadPhaseOctree::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { - return octree.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); +int BroadPhase3DBVH::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); } -int BroadPhaseOctree::cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { - return octree.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); +int BroadPhase3DBVH::cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); } -void *BroadPhaseOctree::_pair_callback(void *self, OctreeElementID p_A, CollisionObject3DSW *p_object_A, int subindex_A, OctreeElementID p_B, CollisionObject3DSW *p_object_B, int subindex_B) { - BroadPhaseOctree *bpo = (BroadPhaseOctree *)(self); +void *BroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject3DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject3DSW *p_object_B, int subindex_B) { + BroadPhase3DBVH *bpo = (BroadPhase3DBVH *)(self); if (!bpo->pair_callback) { return nullptr; } @@ -84,8 +84,8 @@ void *BroadPhaseOctree::_pair_callback(void *self, OctreeElementID p_A, Collisio return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata); } -void BroadPhaseOctree::_unpair_callback(void *self, OctreeElementID p_A, CollisionObject3DSW *p_object_A, int subindex_A, OctreeElementID p_B, CollisionObject3DSW *p_object_B, int subindex_B, void *pairdata) { - BroadPhaseOctree *bpo = (BroadPhaseOctree *)(self); +void BroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject3DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject3DSW *p_object_B, int subindex_B, void *pairdata) { + BroadPhase3DBVH *bpo = (BroadPhase3DBVH *)(self); if (!bpo->unpair_callback) { return; } @@ -93,27 +93,27 @@ void BroadPhaseOctree::_unpair_callback(void *self, OctreeElementID p_A, Collisi bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata); } -void BroadPhaseOctree::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { +void BroadPhase3DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { pair_callback = p_pair_callback; pair_userdata = p_userdata; } -void BroadPhaseOctree::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { +void BroadPhase3DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { unpair_callback = p_unpair_callback; unpair_userdata = p_userdata; } -void BroadPhaseOctree::update() { - // does.. not? +void BroadPhase3DBVH::update() { + bvh.update(); } -BroadPhase3DSW *BroadPhaseOctree::_create() { - return memnew(BroadPhaseOctree); +BroadPhase3DSW *BroadPhase3DBVH::_create() { + return memnew(BroadPhase3DBVH); } -BroadPhaseOctree::BroadPhaseOctree() { - octree.set_pair_callback(_pair_callback, this); - octree.set_unpair_callback(_unpair_callback, this); +BroadPhase3DBVH::BroadPhase3DBVH() { + bvh.set_pair_callback(_pair_callback, this); + bvh.set_unpair_callback(_unpair_callback, this); pair_callback = nullptr; pair_userdata = nullptr; unpair_userdata = nullptr; diff --git a/servers/physics_3d/broad_phase_octree.h b/servers/physics_3d/broad_phase_3d_bvh.h index ee681dda96..30b8b7f2aa 100644 --- a/servers/physics_3d/broad_phase_octree.h +++ b/servers/physics_3d/broad_phase_3d_bvh.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_octree.h */ +/* broad_phase_3d_bvh.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BROAD_PHASE_OCTREE_H -#define BROAD_PHASE_OCTREE_H +#ifndef BROAD_PHASE_3D_BVH_H +#define BROAD_PHASE_3D_BVH_H #include "broad_phase_3d_sw.h" -#include "core/math/octree.h" +#include "core/math/bvh.h" -class BroadPhaseOctree : public BroadPhase3DSW { - Octree<CollisionObject3DSW, true> octree; +class BroadPhase3DBVH : public BroadPhase3DSW { + BVH_Manager<CollisionObject3DSW, true, 128> bvh; - static void *_pair_callback(void *, OctreeElementID, CollisionObject3DSW *, int, OctreeElementID, CollisionObject3DSW *, int); - static void _unpair_callback(void *, OctreeElementID, CollisionObject3DSW *, int, OctreeElementID, CollisionObject3DSW *, int, void *); + static void *_pair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int); + static void _unpair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int, void *); PairCallback pair_callback; void *pair_userdata; @@ -47,7 +47,7 @@ class BroadPhaseOctree : public BroadPhase3DSW { public: // 0 is an invalid ID - virtual ID create(CollisionObject3DSW *p_object, int p_subindex = 0); + virtual ID create(CollisionObject3DSW *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false); virtual void move(ID p_id, const AABB &p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); @@ -66,7 +66,7 @@ public: virtual void update(); static BroadPhase3DSW *_create(); - BroadPhaseOctree(); + BroadPhase3DBVH(); }; -#endif // BROAD_PHASE_OCTREE_H +#endif // BROAD_PHASE_3D_BVH_H diff --git a/servers/physics_3d/broad_phase_3d_sw.h b/servers/physics_3d/broad_phase_3d_sw.h index 283c087b96..98313cb216 100644 --- a/servers/physics_3d/broad_phase_3d_sw.h +++ b/servers/physics_3d/broad_phase_3d_sw.h @@ -48,7 +48,7 @@ public: typedef void (*UnpairCallback)(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_userdata); // 0 is an invalid ID - virtual ID create(CollisionObject3DSW *p_object_, int p_subindex = 0) = 0; + virtual ID create(CollisionObject3DSW *p_object_, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) = 0; virtual void move(ID p_id, const AABB &p_aabb) = 0; virtual void set_static(ID p_id, bool p_static) = 0; virtual void remove(ID p_id) = 0; diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/collision_object_3d_sw.cpp index 293a7e6606..459deb1356 100644 --- a/servers/physics_3d/collision_object_3d_sw.cpp +++ b/servers/physics_3d/collision_object_3d_sw.cpp @@ -146,22 +146,23 @@ void CollisionObject3DSW::_update_shapes() { for (int i = 0; i < shapes.size(); i++) { Shape &s = shapes.write[i]; - if (s.bpid == 0) { - s.bpid = space->get_broadphase()->create(this, i); - space->get_broadphase()->set_static(s.bpid, _static); - } //not quite correct, should compute the next matrix.. AABB shape_aabb = s.shape->get_aabb(); Transform xform = transform * s.xform; shape_aabb = xform.xform(shape_aabb); + shape_aabb.grow_by((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05); s.aabb_cache = shape_aabb; - s.aabb_cache = s.aabb_cache.grow((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05); Vector3 scale = xform.get_basis().get_scale(); s.area_cache = s.shape->get_area() * scale.x * scale.y * scale.z; - space->get_broadphase()->move(s.bpid, s.aabb_cache); + if (s.bpid == 0) { + s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static); + space->get_broadphase()->set_static(s.bpid, _static); + } + + space->get_broadphase()->move(s.bpid, shape_aabb); } } @@ -172,18 +173,19 @@ void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) { for (int i = 0; i < shapes.size(); i++) { Shape &s = shapes.write[i]; - if (s.bpid == 0) { - s.bpid = space->get_broadphase()->create(this, i); - space->get_broadphase()->set_static(s.bpid, _static); - } //not quite correct, should compute the next matrix.. AABB shape_aabb = s.shape->get_aabb(); Transform xform = transform * s.xform; shape_aabb = xform.xform(shape_aabb); - shape_aabb = shape_aabb.merge(AABB(shape_aabb.position + p_motion, shape_aabb.size)); //use motion + shape_aabb.merge_with(AABB(shape_aabb.position + p_motion, shape_aabb.size)); //use motion s.aabb_cache = shape_aabb; + if (s.bpid == 0) { + s.bpid = space->get_broadphase()->create(this, i, shape_aabb, _static); + space->get_broadphase()->set_static(s.bpid, _static); + } + space->get_broadphase()->move(s.bpid, shape_aabb); } } diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index c08e2b5794..f3eb1ae48f 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -30,8 +30,7 @@ #include "physics_server_3d_sw.h" -#include "broad_phase_3d_basic.h" -#include "broad_phase_octree.h" +#include "broad_phase_3d_bvh.h" #include "core/debugger/engine_debugger.h" #include "core/os/os.h" #include "joints/cone_twist_joint_3d_sw.h" @@ -1755,7 +1754,8 @@ void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, PhysicsServer3DSW *PhysicsServer3DSW::singletonsw = nullptr; PhysicsServer3DSW::PhysicsServer3DSW(bool p_using_threads) { singletonsw = this; - BroadPhase3DSW::create_func = BroadPhaseOctree::_create; + BroadPhase3DSW::create_func = BroadPhase3DBVH::_create; + island_count = 0; active_objects = 0; collision_pairs = 0; diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 7f3fc2f8f4..67003a6f64 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -923,10 +923,15 @@ void RendererCanvasCull::canvas_item_add_set_transform(RID p_item, const Transfo void RendererCanvasCull::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); + ERR_FAIL_COND(!p_mesh.is_valid()); Item::CommandMesh *m = canvas_item->alloc_command<Item::CommandMesh>(); ERR_FAIL_COND(!m); m->mesh = p_mesh; + if (canvas_item->skeleton.is_valid()) { + m->mesh_instance = RSG::storage->mesh_instance_create(p_mesh); + RSG::storage->mesh_instance_set_skeleton(m->mesh_instance, canvas_item->skeleton); + } m->texture = p_texture; @@ -996,8 +1001,30 @@ void RendererCanvasCull::canvas_item_set_z_as_relative_to_parent(RID p_item, boo void RendererCanvasCull::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); - + if (canvas_item->skeleton == p_skeleton) { + return; + } canvas_item->skeleton = p_skeleton; + + Item::Command *c = canvas_item->commands; + + while (c) { + if (c->type == Item::Command::TYPE_MESH) { + Item::CommandMesh *cm = static_cast<Item::CommandMesh *>(c); + if (canvas_item->skeleton.is_valid()) { + if (cm->mesh_instance.is_null()) { + cm->mesh_instance = RSG::storage->mesh_instance_create(cm->mesh); + } + RSG::storage->mesh_instance_set_skeleton(cm->mesh_instance, canvas_item->skeleton); + } else { + if (cm->mesh_instance.is_valid()) { + RSG::storage->free(cm->mesh_instance); + cm->mesh_instance = RID(); + } + } + } + c = c->next; + } } void RendererCanvasCull::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) { diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index f08986b021..0e9ef616cb 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -246,10 +246,16 @@ public: RID mesh; Transform2D transform; Color modulate; + RID mesh_instance; RID texture; CommandMesh() { type = TYPE_MESH; } + ~CommandMesh() { + if (mesh_instance.is_valid()) { + RendererStorage::base_singleton->free(mesh_instance); + } + } }; struct CommandMultiMesh : public Command { @@ -262,7 +268,6 @@ public: struct CommandParticles : public Command { RID particles; - RID texture; CommandParticles() { type = TYPE_PARTICLES; } diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h index 919ae2c6da..41aaba0f4c 100644 --- a/servers/rendering/renderer_compositor.h +++ b/servers/rendering/renderer_compositor.h @@ -59,7 +59,22 @@ public: struct BlitToScreen { RID render_target; Rect2i rect; - //lens distorted parameters for VR should go here + + struct { + bool use_layer = false; + uint32_t layer = 0; + } multi_view; + + struct { + //lens distorted parameters for VR + bool apply = false; + Vector2 eye_center; + float k1 = 0.0; + float k2 = 0.0; + + float upscale = 1.0; + float aspect_ratio = 1.0; + } lens_distortion; }; virtual void prepare_for_blitting_render_targets() = 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 aadb7bac19..16c6273ff6 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -536,21 +536,21 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p } } -void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { - //CameraMatrix projection = p_cam_projection; +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) { + //CameraMatrix projection = p_render_data->cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down CameraMatrix correction; correction.set_depth_correction(p_flip_y); - CameraMatrix projection = correction * p_cam_projection; + CameraMatrix projection = correction * p_render_data->cam_projection; //store camera into ubo RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererStorageRD::store_transform(p_cam_transform, scene_state.ubo.camera_matrix); - RendererStorageRD::store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); - scene_state.ubo.z_far = p_zfar; - scene_state.ubo.z_near = p_znear; + 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; @@ -568,17 +568,17 @@ void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_ scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x; scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y; - scene_state.ubo.cluster_shift = get_shift_from_power_of_2(p_cluster_size); - scene_state.ubo.max_cluster_element_count_div_32 = p_max_cluster_elements / 32; + 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; { - uint32_t cluster_screen_width = (p_screen_size.width - 1) / p_cluster_size + 1; - uint32_t cluster_screen_height = (p_screen_size.height - 1) / p_cluster_size + 1; + uint32_t cluster_screen_width = (p_screen_size.width - 1) / p_render_data->cluster_size + 1; + uint32_t cluster_screen_height = (p_screen_size.height - 1) / p_render_data->cluster_size + 1; scene_state.ubo.cluster_type_size = cluster_screen_width * cluster_screen_height * (scene_state.ubo.max_cluster_element_count_div_32 + 32); scene_state.ubo.cluster_width = cluster_screen_width; } - if (p_shadow_atlas.is_valid()) { - Vector2 sas = shadow_atlas_get_size(p_shadow_atlas); + 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; } @@ -594,22 +594,22 @@ void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_ scene_state.ubo.volumetric_fog_enabled = false; scene_state.ubo.fog_enabled = false; - if (p_render_buffers.is_valid()) { - RenderBufferDataForwardClustered *render_buffers = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); + if (p_render_data->render_buffers.is_valid()) { + RenderBufferDataForwardClustered *render_buffers = (RenderBufferDataForwardClustered *)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_buffers)) { + 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_buffers); + 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_buffers); //reverse lookup + 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 { @@ -618,26 +618,26 @@ void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_ } } #if 0 - if (p_render_buffers.is_valid() && render_buffers_is_sdfgi_enabled(p_render_buffers)) { - scene_state.ubo.sdfgi_cascade_count = render_buffers_get_sdfgi_cascade_count(p_render_buffers); - scene_state.ubo.sdfgi_probe_axis_size = render_buffers_get_sdfgi_cascade_probe_count(p_render_buffers); + if (p_render_data->render_buffers.is_valid() && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { + scene_state.ubo.sdfgi_cascade_count = render_buffers_get_sdfgi_cascade_count(p_render_data->render_buffers); + scene_state.ubo.sdfgi_probe_axis_size = render_buffers_get_sdfgi_cascade_probe_count(p_render_data->render_buffers); scene_state.ubo.sdfgi_cascade_probe_size[0] = scene_state.ubo.sdfgi_probe_axis_size - 1; //float version for performance scene_state.ubo.sdfgi_cascade_probe_size[1] = scene_state.ubo.sdfgi_probe_axis_size - 1; scene_state.ubo.sdfgi_cascade_probe_size[2] = scene_state.ubo.sdfgi_probe_axis_size - 1; - float csize = render_buffers_get_sdfgi_cascade_size(p_render_buffers); + float csize = render_buffers_get_sdfgi_cascade_size(p_render_data->render_buffers); scene_state.ubo.sdfgi_probe_to_uvw = 1.0 / float(scene_state.ubo.sdfgi_cascade_probe_size[0]); float occ_bias = 0.0; scene_state.ubo.sdfgi_occlusion_bias = occ_bias / csize; - scene_state.ubo.sdfgi_use_occlusion = render_buffers_is_sdfgi_using_occlusion(p_render_buffers); - scene_state.ubo.sdfgi_energy = render_buffers_get_sdfgi_energy(p_render_buffers); + scene_state.ubo.sdfgi_use_occlusion = render_buffers_is_sdfgi_using_occlusion(p_render_data->render_buffers); + scene_state.ubo.sdfgi_energy = render_buffers_get_sdfgi_energy(p_render_data->render_buffers); float cascade_voxel_size = (csize / scene_state.ubo.sdfgi_cascade_probe_size[0]); float occlusion_clamp = (cascade_voxel_size - 0.5) / cascade_voxel_size; scene_state.ubo.sdfgi_occlusion_clamp[0] = occlusion_clamp; scene_state.ubo.sdfgi_occlusion_clamp[1] = occlusion_clamp; scene_state.ubo.sdfgi_occlusion_clamp[2] = occlusion_clamp; - scene_state.ubo.sdfgi_normal_bias = (render_buffers_get_sdfgi_normal_bias(p_render_buffers) / csize) * scene_state.ubo.sdfgi_cascade_probe_size[0]; + scene_state.ubo.sdfgi_normal_bias = (render_buffers_get_sdfgi_normal_bias(p_render_data->render_buffers) / csize) * scene_state.ubo.sdfgi_cascade_probe_size[0]; //vec2 tex_pixel_size = 1.0 / vec2(ivec2( (OCT_SIZE+2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE+2) * params.probe_axis_size ) ); //vec3 probe_uv_offset = (ivec3(OCT_SIZE+2,OCT_SIZE+2,(OCT_SIZE+2) * params.probe_axis_size)) * tex_pixel_size.xyx; @@ -658,14 +658,14 @@ void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_ for (uint32_t i = 0; i < scene_state.ubo.sdfgi_cascade_count; i++) { SceneState::UBO::SDFGICascade &c = scene_state.ubo.sdfgi_cascades[i]; - Vector3 pos = render_buffers_get_sdfgi_cascade_offset(p_render_buffers, i); - pos -= p_cam_transform.origin; //make pos local to camera, to reduce numerical error + Vector3 pos = render_buffers_get_sdfgi_cascade_offset(p_render_data->render_buffers, i); + pos -= p_render_data->cam_transform.origin; //make pos local to camera, to reduce numerical error c.position[0] = pos.x; c.position[1] = pos.y; c.position[2] = pos.z; - c.to_probe = 1.0 / render_buffers_get_sdfgi_cascade_probe_size(p_render_buffers, i); + c.to_probe = 1.0 / render_buffers_get_sdfgi_cascade_probe_size(p_render_data->render_buffers, i); - Vector3i probe_ofs = render_buffers_get_sdfgi_cascade_probe_offset(p_render_buffers, i); + Vector3i probe_ofs = render_buffers_get_sdfgi_cascade_probe_offset(p_render_data->render_buffers, i); c.probe_world_offset[0] = probe_ofs.x; c.probe_world_offset[1] = probe_ofs.y; c.probe_world_offset[2] = probe_ofs.z; @@ -682,18 +682,18 @@ void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_ scene_state.ubo.use_reflection_cubemap = false; scene_state.ubo.ssao_enabled = false; - } else if (is_environment(p_environment)) { - RS::EnvironmentBG env_bg = environment_get_background(p_environment); - RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_environment); + } 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 = environment_get_bg_energy(p_environment); + float bg_energy = environment_get_bg_energy(p_render_data->environment); scene_state.ubo.ambient_light_color_energy[3] = bg_energy; - scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_environment); + 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_environment); + Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); color = color.to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; @@ -702,15 +702,15 @@ void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_ scene_state.ubo.use_ambient_light = true; scene_state.ubo.use_ambient_cubemap = false; } else { - float energy = environment_get_ambient_light_energy(p_environment); - Color color = environment_get_ambient_light_color(p_environment); + float energy = environment_get_ambient_light_energy(p_render_data->environment); + Color color = environment_get_ambient_light_color(p_render_data->environment); color = color.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_environment); - sky_transform = sky_transform.inverse() * p_cam_transform.basis; + Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); + sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; RendererStorageRD::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; @@ -718,43 +718,43 @@ void RenderForwardClustered::_setup_environment(RID p_environment, RID p_render_ } //specular - RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_environment); + 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_is_ssao_enabled(p_environment); - scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_environment); - scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_environment); + scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_render_data->environment); + scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment); + scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment); - Color ao_color = environment_get_ao_color(p_environment).to_linear(); + Color ao_color = environment_get_ao_color(p_render_data->environment).to_linear(); scene_state.ubo.ao_color[0] = ao_color.r; scene_state.ubo.ao_color[1] = ao_color.g; scene_state.ubo.ao_color[2] = ao_color.b; scene_state.ubo.ao_color[3] = ao_color.a; - scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_environment); - scene_state.ubo.fog_density = environment_get_fog_density(p_environment); - scene_state.ubo.fog_height = environment_get_fog_height(p_environment); - scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_environment); + scene_state.ubo.fog_enabled = environment_is_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); if (scene_state.ubo.fog_height_density >= 0.0001) { scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density; } - scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_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_environment).to_linear(); - float fog_energy = environment_get_fog_light_energy(p_environment); + Color fog_color = environment_get_fog_light_color(p_render_data->environment).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_environment); + scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment); } else { - if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { + if (p_render_data->reflection_probe.is_valid() && storage->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; @@ -867,7 +867,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, u } } -void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_append) { +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) { if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -876,9 +876,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con } uint32_t lightmap_captures_used = 0; - Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(Vector3::AXIS_Z)); - near_plane.d += p_cam_projection.get_z_near(); - float z_max = p_cam_projection.get_z_far() - p_cam_projection.get_z_near(); + Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z)); + 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(); RenderList *rl = &render_list[p_render_list]; _update_dirty_geometry_instances(); @@ -892,8 +892,8 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con //fill list - for (int i = 0; i < (int)p_instances.size(); i++) { - GeometryInstanceForwardClustered *inst = static_cast<GeometryInstanceForwardClustered *>(p_instances[i]); + for (int i = 0; i < (int)p_render_data->instances->size(); i++) { + GeometryInstanceForwardClustered *inst = static_cast<GeometryInstanceForwardClustered *>((*p_render_data->instances)[i]); Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); inst->depth = near_plane.distance_to(support_min); @@ -987,13 +987,13 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con // LOD - if (p_screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { //lod - Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_lod_plane.normal); - Vector3 lod_support_max = inst->transformed_aabb.get_support(p_lod_plane.normal); + 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); - float distance_min = p_lod_plane.distance_to(lod_support_min); - float distance_max = p_lod_plane.distance_to(lod_support_max); + 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 = 0.0; @@ -1006,7 +1006,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con distance = -distance_max; } - surf->sort.lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_lod_distance_multiplier, p_screen_lod_threshold); + surf->sort.lod_index = 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_lod_threshold); } else { surf->sort.lod_index = 0; } @@ -1090,28 +1090,21 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps } } -void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { +void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RenderBufferDataForwardClustered *render_buffer = nullptr; - if (p_render_buffer.is_valid()) { - render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffer); + if (p_render_data->render_buffers.is_valid()) { + render_buffer = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); } - RendererSceneEnvironmentRD *env = get_environment(p_environment); + RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); //first of all, make a new render pass //fill up ubo RENDER_TIMESTAMP("Setup 3D Scene"); - float lod_distance_multiplier = p_cam_projection.get_lod_multiplier(); - Plane lod_camera_plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z)); - - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { - p_screen_lod_threshold = 0.0; - } - //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size; - Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); + Vector2 vp_he = p_render_data->cam_projection.get_viewport_half_extents(); scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; @@ -1136,29 +1129,29 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform opaque_framebuffer = render_buffer->color_fb; - if (p_gi_probes.size() > 0) { + if (p_render_data->gi_probes->size() > 0) { using_giprobe = true; } - if (!p_environment.is_valid() && using_giprobe) { + if (!p_render_data->environment.is_valid() && using_giprobe) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE; - } else if (p_environment.is_valid() && (environment_is_ssr_enabled(p_environment) || environment_is_sdfgi_enabled(p_environment) || using_giprobe)) { - if (environment_is_sdfgi_enabled(p_environment)) { + } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_giprobe)) { + if (environment_is_sdfgi_enabled(p_render_data->environment)) { depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also giprobe using_sdfgi = true; } else { depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } - if (environment_is_ssr_enabled(p_environment)) { + if (environment_is_ssr_enabled(p_render_data->environment)) { render_buffer->ensure_specular(); using_separate_specular = true; using_ssr = true; opaque_specular_framebuffer = render_buffer->color_specular_fb; } - } else if (p_environment.is_valid() && (environment_is_ssao_enabled(p_environment) || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { + } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } @@ -1183,17 +1176,18 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform } alpha_framebuffer = opaque_framebuffer; - } else if (p_reflection_probe.is_valid()) { - uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe); + } 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; screen_size.y = resolution; - opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass); - depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_reflection_probe, p_reflection_probe_pass); + opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); alpha_framebuffer = opaque_framebuffer; - if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { - p_environment = RID(); //no environment on interiors + if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + p_render_data->environment = RID(); //no environment on interiors + env = nullptr; } reverse_cull = true; // for some reason our views are inverted @@ -1203,13 +1197,13 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform RD::get_singleton()->draw_command_begin_label("Render Setup"); - _setup_lightmaps(p_lightmaps, p_cam_transform); - _setup_giprobes(p_gi_probes); - _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); + _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform); + _setup_giprobes(*p_render_data->gi_probes); + _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_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi, using_sdfgi || using_giprobe, lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_giprobe); render_list[RENDER_LIST_OPAQUE].sort_by_key(); render_list[RENDER_LIST_ALPHA].sort_by_depth(); _fill_instance_data(RENDER_LIST_OPAQUE); @@ -1234,26 +1228,26 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black - } else if (is_environment(p_environment)) { - RS::EnvironmentBG bg_mode = environment_get_background(p_environment); - float bg_energy = environment_get_bg_energy(p_environment); + } else if (is_environment(p_render_data->environment)) { + RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment); + float bg_energy = environment_get_bg_energy(p_render_data->environment); switch (bg_mode) { case RS::ENV_BG_CLEAR_COLOR: { clear_color = p_default_bg_color; clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (render_buffers_has_volumetric_fog(p_render_buffer) || environment_is_fog_enabled(p_environment)) { + if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } } break; case RS::ENV_BG_COLOR: { - clear_color = environment_get_bg_color(p_environment); + clear_color = environment_get_bg_color(p_render_data->environment); clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (render_buffers_has_volumetric_fog(p_render_buffer) || environment_is_fog_enabled(p_environment)) { + if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } @@ -1273,21 +1267,21 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform } } // setup sky if used for ambient, reflections, or background - if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_environment) == RS::ENV_AMBIENT_SOURCE_SKY) { + 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"); - CameraMatrix projection = p_cam_projection; - if (p_reflection_probe.is_valid()) { + CameraMatrix projection = p_render_data->cam_projection; + if (p_render_data->reflection_probe.is_valid()) { CameraMatrix correction; correction.set_depth_correction(true); - projection = correction * p_cam_projection; + projection = correction * p_render_data->cam_projection; } - sky.setup(env, p_render_buffer, projection, p_cam_transform, screen_size, this); + sky.setup(env, p_render_data->render_buffers, projection, p_render_data->cam_transform, screen_size, this); RID sky_rid = env->sky; if (sky_rid.is_valid()) { - sky.update(env, projection, p_cam_transform, time); + sky.update(env, projection, p_render_data->cam_transform, time); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid @@ -1303,11 +1297,11 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; bool depth_pre_pass = depth_framebuffer.is_valid(); - bool using_ssao = depth_pre_pass && p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment); + bool using_ssao = depth_pre_pass && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_is_ssao_enabled(p_render_data->environment); bool continue_depth = false; if (depth_pre_pass) { //depth pre pass - bool needs_pre_resolve = _needs_post_prepass_render(using_sdfgi || using_giprobe); + bool needs_pre_resolve = _needs_post_prepass_render(p_render_data, using_sdfgi || using_giprobe); if (needs_pre_resolve) { RENDER_TIMESTAMP("GI + Render Depth Pre-Pass (parallel)"); } else { @@ -1318,21 +1312,21 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear); RD::get_singleton()->draw_list_end(); //start compute processes here, so they run at the same time as depth pre-pass - _post_prepass_render(using_sdfgi || using_giprobe); + _post_prepass_render(p_render_data, using_sdfgi || using_giprobe); } RD::get_singleton()->draw_command_begin_label("Render Depth Pre-Pass"); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID()); bool finish_depth = using_ssao || using_sdfgi || using_giprobe; - 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, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + 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, render_buffer == nullptr, 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_lod_threshold); _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(); if (needs_pre_resolve) { - _pre_resolve_render(using_sdfgi || using_giprobe); + _pre_resolve_render(p_render_data, using_sdfgi || using_giprobe); } if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { @@ -1353,17 +1347,17 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform continue_depth = !finish_depth; } - _pre_opaque_render(using_ssao, using_sdfgi || using_giprobe, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->giprobe_buffer : RID()); + _pre_opaque_render(p_render_data, using_ssao, using_sdfgi || using_giprobe, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->giprobe_buffer : RID()); RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); - scene_state.ubo.directional_light_count = _get_render_state_directional_light_count(); + scene_state.ubo.directional_light_count = p_render_data->directional_light_count; - _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.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, p_render_data->render_buffers.is_valid()); RENDER_TIMESTAMP("Render Opaque Pass"); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_cluster_buffer, p_gi_probes, p_lightmaps, true); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true); bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss; bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss; @@ -1384,7 +1378,7 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform } RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_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, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + 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, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, 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_lod_threshold); _render_list_with_threads(&render_list_params, 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 @@ -1402,11 +1396,11 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform CameraMatrix dc; dc.set_depth_correction(true); - CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse()); + CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_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 GIProbes"); - for (int i = 0; i < (int)p_gi_probes.size(); i++) { - gi.debug_giprobe(p_gi_probes[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); + for (int i = 0; i < (int)p_render_data->gi_probes->size(); i++) { + gi.debug_giprobe((*p_render_data->gi_probes)[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); } RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_list_end(); @@ -1419,10 +1413,10 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform CameraMatrix dc; dc.set_depth_correction(true); - CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse()); + CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_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 SDFGI"); - _debug_sdfgi_probes(p_render_buffer, draw_list, opaque_framebuffer, cm); + _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, opaque_framebuffer, cm); RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_list_end(); } @@ -1430,14 +1424,14 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform if (draw_sky || draw_sky_fog_only) { RENDER_TIMESTAMP("Render Sky"); - CameraMatrix projection = p_cam_projection; - if (p_reflection_probe.is_valid()) { + CameraMatrix projection = p_render_data->cam_projection; + if (p_render_data->reflection_probe.is_valid()) { CameraMatrix correction; correction.set_depth_correction(true); - projection = correction * p_cam_projection; + projection = correction * p_render_data->cam_projection; } RD::get_singleton()->draw_command_begin_label("Draw Sky"); - sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_cam_transform, time); + sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_render_data->cam_transform, time); RD::get_singleton()->draw_command_end_label(); } @@ -1456,14 +1450,14 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform if (using_sss) { RENDER_TIMESTAMP("Sub Surface Scattering"); RD::get_singleton()->draw_command_begin_label("Process Sub Surface Scattering"); - _process_sss(p_render_buffer, p_cam_projection); + _process_sss(p_render_data->render_buffers, p_render_data->cam_projection); RD::get_singleton()->draw_command_end_label(); } if (using_ssr) { RENDER_TIMESTAMP("Screen Space Reflection"); RD::get_singleton()->draw_command_begin_label("Process Screen Space Reflections"); - _process_ssr(p_render_buffer, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_environment, p_cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); + _process_ssr(p_render_data->render_buffers, render_buffer->color_fb, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED); RD::get_singleton()->draw_command_end_label(); } else { //just mix specular back @@ -1476,12 +1470,12 @@ void RenderForwardClustered::_render_scene(RID p_render_buffer, const Transform RD::get_singleton()->draw_command_begin_label("Render Transparent Pass"); - rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_cluster_buffer, p_gi_probes, p_lightmaps, true); + rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true); - _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_cluster_size, p_max_cluster_elements, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); + _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); { - 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, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + 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, render_buffer == nullptr, 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_lod_threshold); _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); } @@ -1509,18 +1503,31 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page SceneState::ShadowPass shadow_pass; + RenderDataRD render_data; + render_data.cam_projection = p_projection; + render_data.cam_transform = p_transform; + render_data.z_far = p_zfar; + render_data.z_near = 0.0; + 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; + scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; - _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), !p_flip_y, Color(), 0, p_zfar, false, p_use_pancake, shadow_pass_index); + _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) { - p_screen_lod_threshold = 0.0; + render_data.screen_lod_threshold = 0.0; + } else { + render_data.screen_lod_threshold = p_screen_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, p_instances, pass_mode, p_projection, p_transform, false, false, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, true); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, 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, render_list_from, render_list_size, false); @@ -1539,8 +1546,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_lod_threshold = p_screen_lod_threshold; - shadow_pass.lod_distance_multiplier = p_lod_distance_multiplier; + shadow_pass.screen_lod_threshold = render_data.screen_lod_threshold; + shadow_pass.lod_distance_multiplier = render_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); @@ -1558,7 +1565,7 @@ void RenderForwardClustered::_render_shadow_process() { for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { //render passes need to be configured after instance buffer is done, since they need the latest version SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; - shadow_pass.rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>(), false, i); + shadow_pass.rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), false, i); } RD::get_singleton()->draw_command_end_label(); @@ -1583,18 +1590,27 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); + RenderDataRD render_data; + render_data.cam_projection = p_cam_projection; + render_data.cam_transform = p_cam_transform; + render_data.z_near = 0.0; + render_data.z_far = p_cam_projection.get_z_far(); + 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; - _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false); + _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); PassMode pass_mode = PASS_MODE_SHADOW; - _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, p_cam_projection, p_cam_transform); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); RENDER_TIMESTAMP("Render Collider Heightfield"); @@ -1611,19 +1627,26 @@ void RenderForwardClustered::_render_material(const Transform &p_cam_transform, RD::get_singleton()->draw_command_begin_label("Render Material"); + RenderDataRD render_data; + render_data.cam_projection = p_cam_projection; + render_data.cam_transform = p_cam_transform; + 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; - _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0); + _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, p_cam_projection, p_cam_transform); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); RENDER_TIMESTAMP("Render Material"); @@ -1649,19 +1672,24 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p RD::get_singleton()->draw_command_begin_label("Render UV2"); + RenderDataRD render_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; - _setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0); + _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, CameraMatrix(), Transform()); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); RENDER_TIMESTAMP("Render Material"); @@ -1712,13 +1740,18 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel"); + RenderDataRD render_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 = (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, p_instances, pass_mode, CameraMatrix(), Transform()); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); @@ -1750,28 +1783,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]; - Transform cam_xform; - cam_xform.origin = center + axis * half_extents; - cam_xform.basis.set_axis(0, right); - cam_xform.basis.set_axis(1, up); - cam_xform.basis.set_axis(2, axis); + render_data.cam_transform.origin = center + axis * half_extents; + render_data.cam_transform.basis.set_axis(0, right); + render_data.cam_transform.basis.set_axis(1, up); + render_data.cam_transform.basis.set_axis(2, axis); - //print_line("pass: " + itos(i) + " xform " + cam_xform); + //print_line("pass: " + itos(i) + " xform " + render_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; - CameraMatrix camera_proj; - camera_proj.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size); + render_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)); Transform to_bounds; to_bounds.origin = p_bounds.position; to_bounds.basis.scale(p_bounds.size); - RendererStorageRD::store_transform(to_bounds.affine_inverse() * cam_xform, scene_state.ubo.sdf_to_bounds); + RendererStorageRD::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds); - _setup_environment(RID(), RID(), camera_proj, cam_xform, RID(), true, Vector2(1, 1), 1, 32, RID(), false, Color(), 0, 0); + _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); @@ -1921,13 +1952,13 @@ void RenderForwardClustered::_update_render_base_uniform_set() { } } -RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas, int p_index) { +RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { //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()); RenderBufferDataForwardClustered *rb = nullptr; - if (p_render_buffers.is_valid()) { - rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers); + if (p_render_data && p_render_data->render_buffers.is_valid()) { + rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_data->render_buffers); } //default render buffer and scene state uniform set @@ -1967,7 +1998,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend } { - RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); + 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.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -1984,8 +2015,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture; - if (p_shadow_atlas.is_valid()) { - texture = shadow_atlas_get_texture(p_shadow_atlas); + if (p_render_data && p_render_data->shadow_atlas.is_valid()) { + texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); @@ -2011,8 +2042,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.ids.resize(scene_state.max_lightmaps); RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { - if (i < p_lightmaps.size()) { - RID base = lightmap_instance_get_lightmap(p_lightmaps[i]); + if (p_render_data && i < p_render_data->lightmaps->size()) { + RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); RID rd_texture = storage->texture_get_rd_texture(texture); u.ids.write[i] = rd_texture; @@ -2030,8 +2061,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.ids.resize(MAX_GI_PROBES); RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); for (int i = 0; i < MAX_GI_PROBES; i++) { - if (i < (int)p_gi_probes.size()) { - RID tex = gi.gi_probe_instance_get_texture(p_gi_probes[i]); + if (p_render_data && i < (int)p_render_data->gi_probes->size()) { + RID tex = gi.gi_probe_instance_get_texture((*p_render_data->gi_probes)[i]); if (!tex.is_valid()) { tex = default_tex; } @@ -2048,7 +2079,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - RID cb = p_cluster_buffer.is_valid() ? p_cluster_buffer : scene_shader.default_vec4_xform_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.ids.push_back(cb); uniforms.push_back(u); } @@ -2065,7 +2096,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 10; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID(); + RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); @@ -2085,7 +2116,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 12; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID(); + RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID(); RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); @@ -2095,7 +2126,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID ambient_buffer = p_render_buffers.is_valid() ? render_buffers_get_gi_ambient_texture(p_render_buffers) : RID(); + RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID(); RID texture = ambient_buffer.is_valid() ? ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); @@ -2105,7 +2136,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 14; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - RID reflection_buffer = p_render_buffers.is_valid() ? render_buffers_get_gi_reflection_texture(p_render_buffers) : RID(); + RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID(); RID texture = reflection_buffer.is_valid() ? reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); @@ -2115,8 +2146,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 15; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID t; - if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) { - t = render_buffers_get_sdfgi_irradiance_probes(p_render_buffers); + 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 = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); } @@ -2127,8 +2158,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 16; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) { - u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers)); + if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { + u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers)); } else { u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } @@ -2138,7 +2169,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 17; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer()); + u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_data->render_buffers) : render_buffers_get_default_gi_probe_buffer()); uniforms.push_back(u); } { @@ -2146,8 +2177,8 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend u.binding = 18; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID vfog = RID(); - if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) { - vfog = render_buffers_get_volumetric_fog_texture(p_render_buffers); + 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 = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); } 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 4b998a9e76..bed3c3b219 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -122,7 +122,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _update_render_base_uniform_set(); RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture); - RID _setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, RID p_cluster_buffer, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas = false, int p_index = 0); + RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); enum PassMode { PASS_MODE_COLOR, @@ -349,7 +349,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { static RenderForwardClustered *singleton; - void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); + void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); void _setup_giprobes(const PagedArray<RID> &p_giprobes); void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform); @@ -373,7 +373,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _update_instance_data_buffer(RenderListType p_render_list); void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); - void _fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, const Plane &p_lod_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, bool p_append = false); + 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); Map<Size2i, RID> sdfgi_framebuffer_size_cache; @@ -566,7 +566,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { RenderList render_list[RENDER_LIST_MAX]; protected: - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_max_cluster_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold); + virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color); virtual void _render_shadow_begin(); virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true); 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 041476adf3..4e93fa5333 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -125,13 +125,13 @@ bool RenderForwardMobile::free(RID p_rid) { /* Render functions */ -RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas, int p_index) { +RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { //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; - if (p_render_buffers.is_valid()) { - rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffers); + if (p_render_data && p_render_data->render_buffers.is_valid()) { + rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); } // default render buffer and scene state uniform set @@ -162,7 +162,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ } { - RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); + 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.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -179,8 +179,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.binding = 4; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture; - if (p_shadow_atlas.is_valid()) { - texture = shadow_atlas_get_texture(p_shadow_atlas); + if (p_render_data && p_render_data->shadow_atlas.is_valid()) { + texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); @@ -208,8 +208,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.ids.resize(scene_state.max_lightmaps); RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { - if (i < p_lightmaps.size()) { - RID base = lightmap_instance_get_lightmap(p_lightmaps[i]); + if (p_render_data && i < p_render_data->lightmaps->size()) { + RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); RID texture = storage->lightmap_get_texture(base); RID rd_texture = storage->texture_get_rd_texture(texture); u.ids.write[i] = rd_texture; @@ -265,7 +265,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_buffers) : RID(); + RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID(); RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); @@ -306,29 +306,16 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c } } -void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_cluster_max_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { - // These are UNUSED here and will not have data parsed from RendererSceneRenderRD: - // - p_gi_probes - // - p_cluster_buffer - // - p_cluster_size - // - p_cluster_max_elements - +void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { RenderBufferDataForwardMobile *render_buffer = nullptr; - if (p_render_buffer.is_valid()) { - render_buffer = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffer); + if (p_render_data->render_buffers.is_valid()) { + render_buffer = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_data->render_buffers); } - RendererSceneEnvironmentRD *env = get_environment(p_environment); + RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment); RENDER_TIMESTAMP("Setup 3D Scene"); - float lod_distance_multiplier = p_cam_projection.get_lod_multiplier(); - Plane lod_camera_plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z)); - - if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { - p_screen_lod_threshold = 0.0; - } - - Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); + Vector2 vp_he = p_render_data->cam_projection.get_viewport_half_extents(); scene_state.ubo.viewport_size[0] = vp_he.x; scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; @@ -349,16 +336,17 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ opaque_framebuffer = render_buffer->color_fb; alpha_framebuffer = opaque_framebuffer; - } else if (p_reflection_probe.is_valid()) { - uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe); + } 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; screen_size.y = resolution; - opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass); + opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); alpha_framebuffer = opaque_framebuffer; - if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { - p_environment = RID(); //no environment on interiors + if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + p_render_data->environment = RID(); //no environment on interiors + env = nullptr; } reverse_cull = true; @@ -368,12 +356,12 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ RD::get_singleton()->draw_command_begin_label("Render Setup"); - _setup_lightmaps(p_lightmaps, p_cam_transform); - _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); + _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform); + _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) - _fill_render_list(RENDER_LIST_OPAQUE, p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR); render_list[RENDER_LIST_OPAQUE].sort_by_key(); render_list[RENDER_LIST_ALPHA].sort_by_depth(); @@ -395,9 +383,9 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black - } else if (is_environment(p_environment)) { - RS::EnvironmentBG bg_mode = environment_get_background(p_environment); - float bg_energy = environment_get_bg_energy(p_environment); + } else if (is_environment(p_render_data->environment)) { + RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment); + float bg_energy = environment_get_bg_energy(p_render_data->environment); switch (bg_mode) { case RS::ENV_BG_CLEAR_COLOR: { clear_color = p_default_bg_color; @@ -405,19 +393,19 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ clear_color.g *= bg_energy; clear_color.b *= bg_energy; /* - if (render_buffers_has_volumetric_fog(p_render_buffer) || environment_is_fog_enabled(p_environment)) { + if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } */ } break; case RS::ENV_BG_COLOR: { - clear_color = environment_get_bg_color(p_environment); + clear_color = environment_get_bg_color(p_render_data->environment); clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; /* - if (render_buffers_has_volumetric_fog(p_render_buffer) || environment_is_fog_enabled(p_environment)) { + if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { draw_sky_fog_only = true; storage->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.to_linear())); } @@ -438,21 +426,21 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ } } // setup sky if used for ambient, reflections, or background - if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_environment) == RS::ENV_AMBIENT_SOURCE_SKY) { + 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"); - CameraMatrix projection = p_cam_projection; - if (p_reflection_probe.is_valid()) { + CameraMatrix projection = p_render_data->cam_projection; + if (p_render_data->reflection_probe.is_valid()) { CameraMatrix correction; correction.set_depth_correction(true); - projection = correction * p_cam_projection; + projection = correction * p_render_data->cam_projection; } - sky.setup(env, p_render_buffer, projection, p_cam_transform, screen_size, this); + sky.setup(env, p_render_data->render_buffers, projection, p_render_data->cam_transform, screen_size, this); RID sky_rid = env->sky; if (sky_rid.is_valid()) { - sky.update(env, projection, p_cam_transform, time); + sky.update(env, projection, p_render_data->cam_transform, time); radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid); } else { // do not try to draw sky if invalid @@ -468,17 +456,17 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ // !BAS! Look into this, seems most of the code in here related to clustered only, may want to move this code into ForwardClustered/RenderForwardMobile before calling it from here // does trigger shadow map rendering so kinda important - _pre_opaque_render(false, false, RID(), RID()); + _pre_opaque_render(p_render_data, false, false, RID(), RID()); RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); - scene_state.ubo.directional_light_count = _get_render_state_directional_light_count(); + scene_state.ubo.directional_light_count = p_render_data->directional_light_count; - _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.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, p_render_data->render_buffers.is_valid()); RENDER_TIMESTAMP("Render Opaque Pass"); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_lightmaps, true); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true); bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss; bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss; @@ -491,7 +479,7 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ Vector<Color> c; c.push_back(clear_color.to_linear()); - 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, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + 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, 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_lod_threshold); _render_list_with_threads(&render_list_params, opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); } @@ -500,14 +488,14 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ if (draw_sky || draw_sky_fog_only) { RENDER_TIMESTAMP("Render Sky"); - CameraMatrix projection = p_cam_projection; - if (p_reflection_probe.is_valid()) { + CameraMatrix projection = p_render_data->cam_projection; + if (p_render_data->reflection_probe.is_valid()) { CameraMatrix correction; correction.set_depth_correction(true); - projection = correction * p_cam_projection; + projection = correction * p_render_data->cam_projection; } RD::get_singleton()->draw_command_begin_label("Draw Sky"); - sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_cam_transform, time); + sky.draw(env, can_continue_color, can_continue_depth, opaque_framebuffer, projection, p_render_data->cam_transform, time); RD::get_singleton()->draw_command_end_label(); } @@ -529,12 +517,12 @@ void RenderForwardMobile::_render_scene(RID p_render_buffer, const Transform &p_ RD::get_singleton()->draw_command_begin_label("Render Transparent Pass"); - rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_lightmaps, true); + rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, true); - _setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); + _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); { - 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, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + 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, 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_lod_threshold); _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); } @@ -564,18 +552,29 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr SceneState::ShadowPass shadow_pass; + RenderDataRD render_data; + render_data.cam_projection = p_projection; + render_data.cam_transform = p_transform; + render_data.z_near = 0.0; + render_data.z_far = p_zfar; + render_data.instances = &p_instances; + 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; - _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), !p_flip_y, Color(), 0, p_zfar, false, p_use_pancake, shadow_pass_index); + _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) { - p_screen_lod_threshold = 0.0; + render_data.screen_lod_threshold = 0.0; + } else { + render_data.screen_lod_threshold = p_screen_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, p_instances, pass_mode, p_projection, p_transform, p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold, true); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, 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, render_list_from, render_list_size, false); @@ -594,8 +593,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_lod_threshold = p_screen_lod_threshold; - shadow_pass.lod_distance_multiplier = p_lod_distance_multiplier; + shadow_pass.screen_lod_threshold = render_data.screen_lod_threshold; + shadow_pass.lod_distance_multiplier = render_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); @@ -612,7 +611,7 @@ void RenderForwardMobile::_render_shadow_process() { for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { //render passes need to be configured after instance buffer is done, since they need the latest version SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; - shadow_pass.rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), PagedArray<RID>(), false, i); + shadow_pass.rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), false, i); } RD::get_singleton()->draw_command_end_label(); @@ -645,14 +644,19 @@ void RenderForwardMobile::_render_material(const Transform &p_cam_transform, con scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = false; - _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); + RenderDataRD render_data; + render_data.cam_projection = p_cam_projection; + render_data.cam_transform = p_cam_transform; + render_data.instances = &p_instances; + + _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, p_cam_projection, p_cam_transform); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), PagedArray<RID>()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); RENDER_TIMESTAMP("Render Material"); @@ -683,14 +687,17 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = true; - _setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); + RenderDataRD render_data; + render_data.instances = &p_instances; + + _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, CameraMatrix(), Transform()); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), PagedArray<RID>()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); RENDER_TIMESTAMP("Render Material"); @@ -747,15 +754,22 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const _update_render_base_uniform_set(); scene_state.ubo.dual_paraboloid_side = 0; - _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false); + RenderDataRD render_data; + render_data.cam_projection = p_cam_projection; + render_data.cam_transform = p_cam_transform; + render_data.z_near = 0.0; + render_data.z_far = p_cam_projection.get_z_far(); + render_data.instances = &p_instances; + + _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); PassMode pass_mode = PASS_MODE_SHADOW; - _fill_render_list(RENDER_LIST_SECONDARY, p_instances, pass_mode, p_cam_projection, p_cam_transform); + _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, RID(), RID(), RID(), RID(), PagedArray<RID>()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID()); RENDER_TIMESTAMP("Render Collider Heightfield"); @@ -902,7 +916,7 @@ RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers return RID(); } -void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold, bool p_append) { +void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append) { if (p_render_list == RENDER_LIST_OPAQUE) { scene_state.used_sss = false; scene_state.used_screen_texture = false; @@ -911,9 +925,9 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } uint32_t lightmap_captures_used = 0; - Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(Vector3::AXIS_Z)); - near_plane.d += p_cam_projection.get_z_near(); - float z_max = p_cam_projection.get_z_far() - p_cam_projection.get_z_near(); + Plane near_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z)); + 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(); RenderList *rl = &render_list[p_render_list]; @@ -929,8 +943,8 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const //fill list - for (int i = 0; i < (int)p_instances.size(); i++) { - GeometryInstanceForwardMobile *inst = static_cast<GeometryInstanceForwardMobile *>(p_instances[i]); + for (int i = 0; i < (int)p_render_data->instances->size(); i++) { + GeometryInstanceForwardMobile *inst = static_cast<GeometryInstanceForwardMobile *>((*p_render_data->instances)[i]); Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); inst->depth = near_plane.distance_to(support_min); @@ -988,13 +1002,13 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const // LOD - if (p_screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { + if (p_render_data->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(surf->surface)) { //lod - Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_lod_plane.normal); - Vector3 lod_support_max = inst->transformed_aabb.get_support(p_lod_plane.normal); + 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); - float distance_min = p_lod_plane.distance_to(lod_support_min); - float distance_max = p_lod_plane.distance_to(lod_support_max); + 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 = 0.0; @@ -1007,7 +1021,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const distance = -distance_max; } - surf->lod_index = storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_lod_distance_multiplier, p_screen_lod_threshold); + surf->lod_index = 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_lod_threshold); } else { surf->lod_index = 0; } @@ -1058,25 +1072,25 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const } } -void RenderForwardMobile::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { +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 - //CameraMatrix projection = p_cam_projection; + //CameraMatrix projection = p_render_data->cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down CameraMatrix correction; correction.set_depth_correction(p_flip_y); - CameraMatrix projection = correction * p_cam_projection; + CameraMatrix projection = correction * p_render_data->cam_projection; //store camera into ubo RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererStorageRD::store_transform(p_cam_transform, scene_state.ubo.camera_matrix); - RendererStorageRD::store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.camera_matrix); + RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); - scene_state.ubo.z_far = p_zfar; - scene_state.ubo.z_near = p_znear; + 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; @@ -1094,19 +1108,8 @@ void RenderForwardMobile::_setup_environment(RID p_environment, RID p_render_buf scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x; scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y; - /* - scene_state.ubo.cluster_shift = get_shift_from_power_of_2(p_cluster_size); - scene_state.ubo.max_cluster_element_count_div_32 = p_max_cluster_elements / 32; - { - uint32_t cluster_screen_width = (p_screen_size.width - 1) / p_cluster_size + 1; - uint32_t cluster_screen_height = (p_screen_size.height - 1) / p_cluster_size + 1; - scene_state.ubo.cluster_type_size = cluster_screen_width * cluster_screen_height * (scene_state.ubo.max_cluster_element_count_div_32 + 32); - scene_state.ubo.cluster_width = cluster_screen_width; - } - */ - - if (p_shadow_atlas.is_valid()) { - Vector2 sas = shadow_atlas_get_size(p_shadow_atlas); + 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; } @@ -1124,22 +1127,22 @@ void RenderForwardMobile::_setup_environment(RID p_environment, RID p_render_buf scene_state.ubo.volumetric_fog_enabled = false; scene_state.ubo.fog_enabled = false; - if (p_render_buffers.is_valid()) { - RenderBufferDataForwardMobile *render_buffers = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffers); + if (p_render_data->render_buffers.is_valid()) { + RenderBufferDataForwardMobile *render_buffers = (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_buffers)) { + 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_buffers); + 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_buffers); //reverse lookup + 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 { @@ -1160,18 +1163,18 @@ void RenderForwardMobile::_setup_environment(RID p_environment, RID p_render_buf scene_state.ubo.use_reflection_cubemap = false; scene_state.ubo.ssao_enabled = false; - } else if (is_environment(p_environment)) { - RS::EnvironmentBG env_bg = environment_get_background(p_environment); - RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_environment); + } 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 = environment_get_bg_energy(p_environment); + float bg_energy = environment_get_bg_energy(p_render_data->environment); scene_state.ubo.ambient_light_color_energy[3] = bg_energy; - scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_environment); + 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_environment); + Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment); color = color.to_linear(); scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; @@ -1180,15 +1183,15 @@ void RenderForwardMobile::_setup_environment(RID p_environment, RID p_render_buf scene_state.ubo.use_ambient_light = true; scene_state.ubo.use_ambient_cubemap = false; } else { - float energy = environment_get_ambient_light_energy(p_environment); - Color color = environment_get_ambient_light_color(p_environment); + float energy = environment_get_ambient_light_energy(p_render_data->environment); + Color color = environment_get_ambient_light_color(p_render_data->environment); color = color.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_environment); - sky_transform = sky_transform.inverse() * p_cam_transform.basis; + Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); + sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; RendererStorageRD::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; @@ -1196,43 +1199,43 @@ void RenderForwardMobile::_setup_environment(RID p_environment, RID p_render_buf } //specular - RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_environment); + 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_is_ssao_enabled(p_environment); - scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_environment); - scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_environment); + scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_render_data->environment); + scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment); + scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment); - Color ao_color = environment_get_ao_color(p_environment).to_linear(); + Color ao_color = environment_get_ao_color(p_render_data->environment).to_linear(); scene_state.ubo.ao_color[0] = ao_color.r; scene_state.ubo.ao_color[1] = ao_color.g; scene_state.ubo.ao_color[2] = ao_color.b; scene_state.ubo.ao_color[3] = ao_color.a; - scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_environment); - scene_state.ubo.fog_density = environment_get_fog_density(p_environment); - scene_state.ubo.fog_height = environment_get_fog_height(p_environment); - scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_environment); + scene_state.ubo.fog_enabled = environment_is_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); if (scene_state.ubo.fog_height_density >= 0.0001) { scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density; } - scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_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_environment).to_linear(); - float fog_energy = environment_get_fog_light_energy(p_environment); + Color fog_color = environment_get_fog_light_color(p_render_data->environment).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_environment); + scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment); } else { - if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { + if (p_render_data->reflection_probe.is_valid() && storage->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; 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 232ad0066b..bf911319f2 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -148,8 +148,8 @@ protected: } }; - RID _setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas = false, int p_index = 0); - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_cluster_max_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold); + RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); + virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color); virtual void _render_shadow_begin(); virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true); @@ -167,13 +167,13 @@ protected: void _update_render_base_uniform_set(); virtual RID _render_buffers_get_normal_texture(RID p_render_buffers); - void _fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, const Plane &p_lod_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, bool p_append = false); + void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false); void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); // void _update_instance_data_buffer(RenderListType p_render_list); static RenderForwardMobile *singleton; - void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); + void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform); RID render_base_uniform_set; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 377b0fd72d..f448698976 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -705,286 +705,128 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, const Item case Item::Command::TYPE_MESH: case Item::Command::TYPE_MULTIMESH: case Item::Command::TYPE_PARTICLES: { - ERR_PRINT("FIXME: Mesh, MultiMesh and Particles render commands are unimplemented currently, they need to be ported to the 4.0 rendering architecture."); -#ifndef _MSC_VER -#warning Item::Command types for Mesh, MultiMesh and Particles need to be implemented. -#endif - // See #if 0'ed code below to port from GLES3. - } break; - -#if 0 - case Item::Command::TYPE_MESH: { - Item::CommandMesh *mesh = static_cast<Item::CommandMesh *>(c); - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mesh->texture, mesh->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + RID mesh; + RID mesh_instance; + RID texture; + Color modulate(1, 1, 1, 1); + float world_backup[6]; + int instance_count = 1; + + for (int j = 0; j < 6; j++) { + world_backup[j] = push_constant.world[j]; } - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform); - - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); - if (mesh_data) { - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; - // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing - glBindVertexArray(s->array_id); - - glVertexAttrib4f(RS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a); + if (c->type == Item::Command::TYPE_MESH) { + const Item::CommandMesh *m = static_cast<const Item::CommandMesh *>(c); + mesh = m->mesh; + mesh_instance = m->mesh_instance; + texture = m->texture; + modulate = m->modulate; + _update_transform_2d_to_mat2x3(base_transform * m->transform, push_constant.world); + } else if (c->type == Item::Command::TYPE_MULTIMESH) { + const Item::CommandMultiMesh *mm = static_cast<const Item::CommandMultiMesh *>(c); + RID multimesh = mm->multimesh; + mesh = storage->multimesh_get_mesh(multimesh); + texture = mm->texture; + + if (storage->multimesh_get_transform_format(multimesh) != RS::MULTIMESH_TRANSFORM_2D) { + break; + } - if (s->index_array_len) { - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - } else { - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - } + instance_count = storage->multimesh_get_instances_to_draw(multimesh); - glBindVertexArray(0); + RID uniform_set = storage->multimesh_get_2d_uniform_set(multimesh, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); + push_constant.flags |= 1; //multimesh, trails disabled + if (storage->multimesh_uses_colors(multimesh)) { + push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS; } - } - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); + if (storage->multimesh_uses_custom_data(multimesh)) { + push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; + } + } else if (c->type == Item::Command::TYPE_PARTICLES) { + const Item::CommandParticles *pt = static_cast<const Item::CommandParticles *>(c); + ERR_BREAK(storage->particles_get_mode(pt->particles) != RS::PARTICLES_MODE_2D); + if (storage->particles_is_inactive(pt->particles)) { + break; + } + int dpc = storage->particles_get_draw_passes(pt->particles); + if (dpc == 0) { + break; //nothing to draw + } + uint32_t divisor = 1; + instance_count = storage->particles_get_amount(pt->particles, divisor); - } break; - case Item::Command::TYPE_MULTIMESH: { - Item::CommandMultiMesh *mmesh = static_cast<Item::CommandMultiMesh *>(c); + RID uniform_set = storage->particles_get_instance_buffer_uniform_set(pt->particles, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, TRANSFORMS_UNIFORM_SET); - RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); + push_constant.flags |= divisor; + instance_count /= divisor; - if (!multi_mesh) - break; + push_constant.flags |= FLAGS_INSTANCING_HAS_COLORS; + push_constant.flags |= FLAGS_INSTANCING_HAS_CUSTOM_DATA; - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh); + mesh = storage->particles_get_draw_pass_mesh(pt->particles, 0); //higher ones are ignored + texture = pt->texture; + } - if (!mesh_data) + if (mesh.is_null()) { break; + } - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map); + _bind_canvas_texture(p_draw_list, texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != RS::MULTIMESH_CUSTOM_DATA_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); + uint32_t surf_count = storage->mesh_get_surface_count(mesh); + static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } + push_constant.modulation[0] = base_color.r * modulate.r; + push_constant.modulation[1] = base_color.g * modulate.g; + push_constant.modulation[2] = base_color.b * modulate.b; + push_constant.modulation[3] = base_color.a * modulate.a; - int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); - - if (amount == -1) { - amount = multi_mesh->size; + for (int j = 0; j < 4; j++) { + push_constant.src_rect[j] = 0; + push_constant.dst_rect[j] = 0; + push_constant.ninepatch_margins[j] = 0; } - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; - // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing - glBindVertexArray(s->instancing_array_id); + for (uint32_t j = 0; j < surf_count; j++) { + void *surface = storage->mesh_get_surface(mesh, j); - glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer + RS::PrimitiveType primitive = storage->mesh_surface_get_primitive(surface); + ERR_CONTINUE(primitive < 0 || primitive >= RS::PRIMITIVE_MAX); - int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); - glVertexAttribDivisor(9, 1); + uint32_t input_mask = pipeline_variants->variants[light_mode][variant[primitive]].get_vertex_input_mask(); - int color_ofs; + RID vertex_array; + RD::VertexFormatID vertex_format = RD::INVALID_FORMAT_ID; - if (multi_mesh->transform_format == RS::MULTIMESH_TRANSFORM_3D) { - glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); - glVertexAttribDivisor(10, 1); - color_ofs = 12 * 4; + if (mesh_instance.is_valid()) { + storage->mesh_instance_surface_get_vertex_arrays_and_format(mesh_instance, j, input_mask, vertex_array, vertex_format); } else { - glDisableVertexAttribArray(10); - glVertexAttrib4f(10, 0, 0, 1, 0); - color_ofs = 8 * 4; + storage->mesh_surface_get_vertex_arrays_and_format(surface, input_mask, vertex_array, vertex_format); } - int custom_data_ofs = color_ofs; - - switch (multi_mesh->color_format) { - case RS::MULTIMESH_COLOR_NONE: { - glDisableVertexAttribArray(11); - glVertexAttrib4f(11, 1, 1, 1, 1); - } break; - case RS::MULTIMESH_COLOR_8BIT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4; - - } break; - case RS::MULTIMESH_COLOR_FLOAT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4 * 4; - } break; - } + RID pipeline = pipeline_variants->variants[light_mode][variant[primitive]].get_render_pipeline(vertex_format, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - switch (multi_mesh->custom_data_format) { - case RS::MULTIMESH_CUSTOM_DATA_NONE: { - glDisableVertexAttribArray(12); - glVertexAttrib4f(12, 1, 1, 1, 1); - } break; - case RS::MULTIMESH_CUSTOM_DATA_8BIT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - - } break; - case RS::MULTIMESH_CUSTOM_DATA_FLOAT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - } break; - } + RID index_array = storage->mesh_surface_get_index_array(surface, 0); - if (s->index_array_len) { - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - } else { - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); + if (index_array.is_valid()) { + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, index_array); } - glBindVertexArray(0); - } - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - } break; - case Item::Command::TYPE_PARTICLES: { - Item::CommandParticles *particles_cmd = static_cast<Item::CommandParticles *>(c); - - RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles); - if (!particles) - break; - - if (particles->inactive && !particles->emitting) - break; - - glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white - - RenderingServerDefault::redraw_request(); - - storage->particles_request_process(particles_cmd->particles); - //enable instancing - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0)); - } - - if (!particles->use_local_coords) { - Transform2D inv_xf; - inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y)); - inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y)); - inv_xf.set_origin(Vector2(particles->emission_transform.get_origin().x, particles->emission_transform.get_origin().y)); - inv_xf.affine_invert(); + RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, vertex_array); + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf); + RD::get_singleton()->draw_list_draw(p_draw_list, index_array.is_valid(), instance_count); } - glBindVertexArray(data.particle_quad_array); //use particle quad array - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer - - int stride = sizeof(float) * 4 * 6; - - int amount = particles->amount; - - if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_LIFETIME) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, nullptr); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount); - } else { - //split - int split = int(Math::ceil(particles->phase * particles->amount)); - - if (amount - split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount - split); - } - - if (split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, nullptr); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split); - } + for (int j = 0; j < 6; j++) { + push_constant.world[j] = world_backup[j]; } - glBindVertexArray(0); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - } break; -#endif case Item::Command::TYPE_TRANSFORM: { const Item::CommandTransform *transform = static_cast<const Item::CommandTransform *>(c); _update_transform_2d_to_mat2x3(base_transform * transform->xform, push_constant.world); @@ -1437,6 +1279,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p Item *canvas_group_owner = nullptr; + bool update_skeletons = false; + while (ci) { if (ci->copy_back_buffer && canvas_group_owner == nullptr) { backbuffer_copy = true; @@ -1472,9 +1316,27 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p } } + if (ci->skeleton.is_valid()) { + const Item::Command *c = ci->commands; + + while (c) { + if (c->type == Item::Command::TYPE_MESH) { + const Item::CommandMesh *cm = static_cast<const Item::CommandMesh *>(c); + if (cm->mesh_instance.is_valid()) { + storage->mesh_instance_check_for_update(cm->mesh_instance); + update_skeletons = true; + } + } + } + } + if (ci->canvas_group_owner != nullptr) { if (canvas_group_owner == nullptr) { //Canvas group begins here, render until before this item + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); item_count = 0; @@ -1494,6 +1356,11 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p } if (ci == canvas_group_owner) { + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true); item_count = 0; @@ -1506,6 +1373,10 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p if (backbuffer_copy) { //render anything pending, including clearing if no items + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); item_count = 0; @@ -1518,6 +1389,11 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p items[item_count++] = ci; if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { + if (update_skeletons) { + storage->update_mesh_instances(); + update_skeletons = false; + } + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); //then reset item_count = 0; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index cb947d7180..8129cc6c9b 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -67,12 +67,10 @@ class RendererCanvasRenderRD : public RendererCanvasRender { }; enum { - FLAGS_INSTANCING_STRIDE_MASK = 0xF, - FLAGS_INSTANCING_ENABLED = (1 << 4), - FLAGS_INSTANCING_HAS_COLORS = (1 << 5), - FLAGS_INSTANCING_COLOR_8BIT = (1 << 6), - FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 7), - FLAGS_INSTANCING_CUSTOM_DATA_8_BIT = (1 << 8), + + FLAGS_INSTANCING_MASK = 0x7F, + FLAGS_INSTANCING_HAS_COLORS = (1 << 7), + FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8), FLAGS_CLIP_RECT_UV = (1 << 9), FLAGS_TRANSPOSE_RECT = (1 << 10), diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index cb3e67e990..0012ba9c27 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -44,32 +44,40 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID ERR_CONTINUE(texture.is_null()); RID rd_texture = storage->texture_get_rd_texture(texture); ERR_CONTINUE(rd_texture.is_null()); + if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) { Vector<RD::Uniform> uniforms; RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; u.binding = 0; - u.ids.push_back(copy_viewports_sampler); + u.ids.push_back(blit.sampler); u.ids.push_back(rd_texture); uniforms.push_back(u); - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_viewports_rd_shader, 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blit.shader.version_get_shader(blit.shader_version, BLIT_MODE_NORMAL), 0); render_target_descriptors[rd_texture] = uniform_set; } Size2 screen_size(RD::get_singleton()->screen_get_width(p_screen), RD::get_singleton()->screen_get_height(p_screen)); - - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_viewports_rd_pipeline); - RD::get_singleton()->draw_list_bind_index_array(draw_list, copy_viewports_rd_array); + BlitMode mode = p_render_targets[i].lens_distortion.apply ? BLIT_MODE_LENS : p_render_targets[i].multi_view.use_layer ? BLIT_MODE_USE_LAYER : + BLIT_MODE_NORMAL; + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blit.pipelines[mode]); + RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0); - float push_constant[4] = { - p_render_targets[i].rect.position.x / screen_size.width, - p_render_targets[i].rect.position.y / screen_size.height, - p_render_targets[i].rect.size.width / screen_size.width, - p_render_targets[i].rect.size.height / screen_size.height, - }; - RD::get_singleton()->draw_list_set_push_constant(draw_list, push_constant, 4 * sizeof(float)); + blit.push_constant.rect[0] = p_render_targets[i].rect.position.x / screen_size.width; + blit.push_constant.rect[1] = p_render_targets[i].rect.position.y / screen_size.height; + blit.push_constant.rect[2] = p_render_targets[i].rect.size.width / screen_size.width; + blit.push_constant.rect[3] = p_render_targets[i].rect.size.height / screen_size.height; + blit.push_constant.layer = p_render_targets[i].multi_view.layer; + blit.push_constant.eye_center[0] = p_render_targets[i].lens_distortion.eye_center.x; + blit.push_constant.eye_center[1] = p_render_targets[i].lens_distortion.eye_center.y; + blit.push_constant.k1 = p_render_targets[i].lens_distortion.k1; + blit.push_constant.k2 = p_render_targets[i].lens_distortion.k2; + blit.push_constant.upscale = p_render_targets[i].lens_distortion.upscale; + blit.push_constant.aspect_ratio = p_render_targets[i].lens_distortion.aspect_ratio; + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blit.push_constant, sizeof(BlitPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, true); } @@ -96,40 +104,22 @@ void RendererCompositorRD::end_frame(bool p_swap_buffers) { } void RendererCompositorRD::initialize() { - { //create framebuffer copy shader - RenderingDevice::ShaderStageData vert; - vert.shader_stage = RenderingDevice::SHADER_STAGE_VERTEX; - vert.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_VERTEX, - "#version 450\n" - "layout(push_constant, binding = 0, std140) uniform Pos { vec4 dst_rect; } pos;\n" - "layout(location =0) out vec2 uv;\n" - "void main() { \n" - " vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));\n" - " uv = base_arr[gl_VertexIndex];\n" - " vec2 vtx = pos.dst_rect.xy+uv*pos.dst_rect.zw;\n" - " gl_Position = vec4(vtx * 2.0 - 1.0,0.0,1.0);\n" - "}\n"); - - RenderingDevice::ShaderStageData frag; - frag.shader_stage = RenderingDevice::SHADER_STAGE_FRAGMENT; - frag.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_FRAGMENT, - "#version 450\n" - "layout (location = 0) in vec2 uv;\n" - "layout (location = 0) out vec4 color;\n" - "layout (binding = 0) uniform sampler2D src_rt;\n" - "void main() { color=texture(src_rt,uv); }\n"); - - Vector<RenderingDevice::ShaderStageData> source; - source.push_back(vert); - source.push_back(frag); - String error; - copy_viewports_rd_shader = RD::get_singleton()->shader_create(source); - if (!copy_viewports_rd_shader.is_valid()) { - print_line("Failed compilation: " + error); + { + // Initialize blit + Vector<String> blit_modes; + blit_modes.push_back("\n"); + blit_modes.push_back("\n#define USE_LAYER\n"); + blit_modes.push_back("\n#define USE_LAYER\n#define APPLY_LENS_DISTORTION\n"); + + blit.shader.initialize(blit_modes); + + blit.shader_version = blit.shader.version_create(); + + for (int i = 0; i < BLIT_MODE_MAX; i++) { + blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RenderingDevice::PipelineColorBlendState::create_disabled(), 0); } - } - { //create index array for copy shader + //create index array for copy shader Vector<uint8_t> pv; pv.resize(6 * 4); { @@ -142,15 +132,10 @@ void RendererCompositorRD::initialize() { p32[4] = 2; p32[5] = 3; } - copy_viewports_rd_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); - copy_viewports_rd_array = RD::get_singleton()->index_array_create(copy_viewports_rd_index_buffer, 0, 6); - } + blit.index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); + blit.array = RD::get_singleton()->index_array_create(blit.index_buffer, 0, 6); - { //pipeline - copy_viewports_rd_pipeline = RD::get_singleton()->render_pipeline_create(copy_viewports_rd_shader, RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RenderingDevice::PipelineColorBlendState::create_disabled(), 0); - } - { // sampler - copy_viewports_sampler = RD::get_singleton()->sampler_create(RD::SamplerState()); + blit.sampler = RD::get_singleton()->sampler_create(RD::SamplerState()); } } @@ -162,9 +147,9 @@ void RendererCompositorRD::finalize() { memdelete(storage); //only need to erase these, the rest are erased by cascade - RD::get_singleton()->free(copy_viewports_rd_index_buffer); - RD::get_singleton()->free(copy_viewports_rd_shader); - RD::get_singleton()->free(copy_viewports_sampler); + blit.shader.version_free(blit.shader_version); + RD::get_singleton()->free(blit.index_buffer); + RD::get_singleton()->free(blit.sampler); } RendererCompositorRD *RendererCompositorRD::singleton = nullptr; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index b3865de2bf..52552f7ee3 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -38,6 +38,7 @@ #include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h" #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" #include "servers/rendering/renderer_rd/renderer_storage_rd.h" +#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h" class RendererCompositorRD : public RendererCompositor { protected: @@ -45,11 +46,35 @@ protected: RendererStorageRD *storage; RendererSceneRenderRD *scene; - RID copy_viewports_rd_shader; - RID copy_viewports_rd_pipeline; - RID copy_viewports_rd_index_buffer; - RID copy_viewports_rd_array; - RID copy_viewports_sampler; + enum BlitMode { + BLIT_MODE_NORMAL, + BLIT_MODE_USE_LAYER, + BLIT_MODE_LENS, + BLIT_MODE_MAX + }; + + struct BlitPushConstant { + float rect[4]; + + float eye_center[2]; + float k1; + float k2; + + float upscale; + float aspect_ratio; + uint32_t layer; + uint32_t pad1; + }; + + struct Blit { + BlitPushConstant push_constant; + BlitShaderRD shader; + RID shader_version; + RID pipelines[BLIT_MODE_MAX]; + RID index_buffer; + RID array; + RID sampler; + } blit; Map<RID, RID> render_target_descriptors; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp index bc92e0b1ad..b289b17fad 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp @@ -1367,7 +1367,7 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr } } -void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform &p_transform, RendererSceneRenderRD *p_scene_render) { +void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) { /* Update general SDFGI Buffer */ SDFGIData sdfgi_data; diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h index df20011b23..59f5f374d1 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_gi_rd.h @@ -48,7 +48,8 @@ #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" -// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound +// 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; class RendererSceneGIRD { @@ -529,7 +530,7 @@ public: void debug_draw(const CameraMatrix &p_projection, const Transform &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture); void debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform); - void pre_process_gi(const Transform &p_transform, RendererSceneRenderRD *p_scene_render); + void pre_process_gi(const Transform &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render); void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render); void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render); }; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index d7a5d1211c..1f01de1333 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1731,13 +1731,13 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid); } -void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection) { - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); +void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers); ERR_FAIL_COND(!rb); - RendererSceneEnvironmentRD *env = environment_owner.getornull(p_environment); + RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment); //glow (if enabled) - CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); + CameraEffects *camfx = camera_effects_owner.getornull(p_render_data->camera_effects); bool can_use_effects = rb->width >= 8 && rb->height >= 8; @@ -1747,7 +1747,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(RID p_rende } float bokeh_size = camfx->dof_blur_amount * 64.0; - storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_projection.get_z_near(), p_projection.get_z_far(), p_projection.is_orthogonal()); + storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_render_data->z_near, p_render_data->z_far, p_render_data->cam_ortogonal); } if (can_use_effects && env && env->auto_exposure) { @@ -3459,13 +3459,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e rb->volumetric_fog->prev_cam_transform = p_cam_transform; } -uint32_t RendererSceneRenderRD::_get_render_state_directional_light_count() const { - return render_state.directional_light_count; -} - -bool RendererSceneRenderRD::_needs_post_prepass_render(bool p_use_gi) { - if (render_state.render_buffers.is_valid()) { - RenderBuffers *rb = render_buffers_owner.getornull(render_state.render_buffers); +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.getornull(p_render_data->render_buffers); if (rb->sdfgi != nullptr) { return true; } @@ -3473,34 +3469,34 @@ bool RendererSceneRenderRD::_needs_post_prepass_render(bool p_use_gi) { return false; } -void RendererSceneRenderRD::_post_prepass_render(bool p_use_gi) { - if (render_state.render_buffers.is_valid()) { +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.getornull(render_state.render_buffers); + RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers); ERR_FAIL_COND(rb == nullptr); if (rb->sdfgi == nullptr) { return; } - RendererSceneEnvironmentRD *env = environment_owner.getornull(render_state.environment); + RendererSceneEnvironmentRD *env = environment_owner.getornull(p_render_data->environment); rb->sdfgi->update_probes(env, sky.sky_owner.getornull(env->sky)); } } } -void RendererSceneRenderRD::_pre_resolve_render(bool p_use_gi) { - if (render_state.render_buffers.is_valid()) { +void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi) { + if (p_render_data->render_buffers.is_valid()) { if (p_use_gi) { RD::get_singleton()->compute_list_end(); } } } -void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer) { +void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer) { // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time - if (render_state.render_buffers.is_valid() && p_use_gi) { - RenderBuffers *rb = render_buffers_owner.getornull(render_state.render_buffers); + if (p_render_data->render_buffers.is_valid() && p_use_gi) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_data->render_buffers); ERR_FAIL_COND(rb == nullptr); if (rb->sdfgi == nullptr) { return; @@ -3513,8 +3509,8 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R render_state.shadows.clear(); render_state.directional_shadows.clear(); - Plane camera_plane(render_state.cam_transform.origin, -render_state.cam_transform.basis.get_axis(Vector3::AXIS_Z)); - float lod_distance_multiplier = render_state.cam_projection.get_lod_multiplier(); + Plane camera_plane(p_render_data->cam_transform.origin, -p_render_data->cam_transform.basis.get_axis(Vector3::AXIS_Z)); + float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier(); { for (int i = 0; i < render_state.render_shadow_count; i++) { @@ -3531,7 +3527,7 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R //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, render_state.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, render_state.screen_lod_threshold, true, true, true); + _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_lod_threshold, true, true, true); } if (render_state.directional_shadows.size()) { @@ -3545,7 +3541,7 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R // Render GI bool render_shadows = render_state.directional_shadows.size() || render_state.shadows.size(); - bool render_gi = render_state.render_buffers.is_valid() && p_use_gi; + bool render_gi = p_render_data->render_buffers.is_valid() && p_use_gi; if (render_shadows && render_gi) { RENDER_TIMESTAMP("Render GI + Render Shadows (parallel)"); @@ -3561,11 +3557,11 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R //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, render_state.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, render_state.screen_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false); + _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_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false); } //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, render_state.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, render_state.screen_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true); + _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_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true); } _render_shadow_process(); @@ -3573,7 +3569,7 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R //start GI if (render_gi) { - gi.process_gi(render_state.render_buffers, p_normal_roughness_buffer, p_gi_probe_buffer, render_state.environment, render_state.cam_projection, render_state.cam_transform, *render_state.gi_probes, this); + gi.process_gi(p_render_data->render_buffers, p_normal_roughness_buffer, p_gi_probe_buffer, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, *p_render_data->gi_probes, this); } //Do shadow rendering (in parallel with GI) @@ -3585,9 +3581,9 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier } - if (render_state.render_buffers.is_valid()) { + if (p_render_data->render_buffers.is_valid()) { if (p_use_ssao) { - _process_ssao(render_state.render_buffers, render_state.environment, p_normal_roughness_buffer, render_state.cam_projection); + _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_buffer, p_render_data->cam_projection); } } @@ -3595,32 +3591,32 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); if (current_cluster_builder) { - current_cluster_builder->begin(render_state.cam_transform, render_state.cam_projection, !render_state.reflection_probe.is_valid()); + current_cluster_builder->begin(p_render_data->cam_transform, p_render_data->cam_projection, !p_render_data->reflection_probe.is_valid()); } bool using_shadows = true; - if (render_state.reflection_probe.is_valid()) { - if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(render_state.reflection_probe))) { + if (p_render_data->reflection_probe.is_valid()) { + if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { using_shadows = false; } } else { //do not render reflections when rendering a reflection probe - _setup_reflections(*render_state.reflection_probes, render_state.cam_transform.affine_inverse(), render_state.environment); + _setup_reflections(*p_render_data->reflection_probes, p_render_data->cam_transform.affine_inverse(), p_render_data->environment); } uint32_t directional_light_count = 0; uint32_t positional_light_count = 0; - _setup_lights(*render_state.lights, render_state.cam_transform, render_state.shadow_atlas, using_shadows, directional_light_count, positional_light_count); - _setup_decals(*render_state.decals, render_state.cam_transform.affine_inverse()); + _setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count); + _setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse()); - render_state.directional_light_count = directional_light_count; + p_render_data->directional_light_count = directional_light_count; if (current_cluster_builder) { current_cluster_builder->bake_cluster(); } - if (render_state.render_buffers.is_valid()) { + if (p_render_data->render_buffers.is_valid()) { bool directional_shadows = false; for (uint32_t i = 0; i < directional_light_count; i++) { if (cluster.directional_lights[i].shadow_enabled) { @@ -3629,7 +3625,7 @@ void RendererSceneRenderRD::_pre_opaque_render(bool p_use_ssao, bool p_use_gi, R } } if (is_volumetric_supported()) { - _update_volumetric_fog(render_state.render_buffers, render_state.environment, render_state.cam_projection, render_state.cam_transform, render_state.shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.gi_probe_count); + _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->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.gi_probe_count); } } } @@ -3643,24 +3639,37 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & } //assign render data + RenderDataRD render_data; { - render_state.render_buffers = p_render_buffers; - render_state.cam_transform = p_cam_transform; - render_state.cam_projection = p_cam_projection; - render_state.cam_ortogonal = p_cam_projection.is_orthogonal(); - render_state.instances = &p_instances; - render_state.lights = &p_lights; - render_state.reflection_probes = &p_reflection_probes; - render_state.gi_probes = &p_gi_probes; - render_state.decals = &p_decals; - render_state.lightmaps = &p_lightmaps; - render_state.environment = p_environment; - render_state.camera_effects = p_camera_effects; - render_state.shadow_atlas = p_shadow_atlas; - render_state.reflection_atlas = p_reflection_atlas; - render_state.reflection_probe = p_reflection_probe; - render_state.reflection_probe_pass = p_reflection_probe_pass; - render_state.screen_lod_threshold = p_screen_lod_threshold; + render_data.render_buffers = p_render_buffers; + + render_data.cam_transform = p_cam_transform; + render_data.cam_projection = p_cam_projection; + render_data.cam_ortogonal = p_cam_projection.is_orthogonal(); // !BAS! Shouldn't this be p_cam_ortogonal ? + render_data.z_near = p_cam_projection.get_z_near(); + render_data.z_far = p_cam_projection.get_z_far(); + + render_data.instances = &p_instances; + render_data.lights = &p_lights; + render_data.reflection_probes = &p_reflection_probes; + render_data.gi_probes = &p_gi_probes; + render_data.decals = &p_decals; + render_data.lightmaps = &p_lightmaps; + render_data.environment = p_environment; + render_data.camera_effects = p_camera_effects; + render_data.shadow_atlas = p_shadow_atlas; + render_data.reflection_atlas = p_reflection_atlas; + render_data.reflection_probe = p_reflection_probe; + render_data.reflection_probe_pass = p_reflection_probe_pass; + + render_data.lod_distance_multiplier = p_cam_projection.get_lod_multiplier(); + render_data.lod_camera_plane = Plane(p_cam_transform.get_origin(), -p_cam_transform.basis.get_axis(Vector3::AXIS_Z)); + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { + render_data.screen_lod_threshold = 0.0; + } else { + render_data.screen_lod_threshold = p_screen_lod_threshold; + } render_state.render_shadows = p_render_shadows; render_state.render_shadow_count = p_render_shadow_count; @@ -3672,9 +3681,9 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & PagedArray<RID> empty; if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { - render_state.lights = ∅ - render_state.reflection_probes = ∅ - render_state.gi_probes = ∅ + render_data.lights = ∅ + render_data.reflection_probes = ∅ + render_data.gi_probes = ∅ } //sdfgi first @@ -3704,11 +3713,11 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & } } - if (render_buffers_owner.owns(render_state.render_buffers)) { - // render_state.render_buffers == p_render_buffers so we can use our already retrieved rb + if (render_buffers_owner.owns(render_data.render_buffers)) { + // 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_state.reflection_probe)) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(render_state.reflection_probe); + } else if (reflection_probe_instance_owner.owns(render_data.reflection_probe)) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(render_data.reflection_probe); ReflectionAtlas *ra = reflection_atlas_owner.getornull(rpi->atlas); if (!ra) { ERR_PRINT("reflection probe has no reflection atlas! Bug?"); @@ -3724,12 +3733,12 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & if (rb != nullptr && rb->sdfgi != nullptr) { rb->sdfgi->update_cascades(); - rb->sdfgi->pre_process_gi(p_cam_transform, this); + rb->sdfgi->pre_process_gi(p_cam_transform, &render_data, this); } render_state.gi_probe_count = 0; if (rb != nullptr && rb->sdfgi != nullptr) { - gi.setup_giprobes(render_state.render_buffers, render_state.cam_transform, *render_state.gi_probes, render_state.gi_probe_count, this); + gi.setup_giprobes(render_data.render_buffers, render_data.cam_transform, *render_data.gi_probes, render_state.gi_probe_count, this); rb->sdfgi->update_light(); } @@ -3737,11 +3746,13 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & render_state.depth_prepass_used = false; //calls _pre_opaque_render between depth pre-pass and opaque pass if (current_cluster_builder != nullptr) { - _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, *render_state.gi_probes, p_lightmaps, p_environment, current_cluster_builder->get_cluster_buffer(), current_cluster_builder->get_cluster_size(), current_cluster_builder->get_max_cluster_elements(), p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold); - } else { - _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, *render_state.gi_probes, p_lightmaps, p_environment, RID(), 0, 0, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold); + render_data.cluster_buffer = current_cluster_builder->get_cluster_buffer(); + render_data.cluster_size = current_cluster_builder->get_cluster_size(); + render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements(); } + _render_scene(&render_data, clear_color); + if (p_render_buffers.is_valid()) { if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) { ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX; @@ -3768,7 +3779,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform & RENDER_TIMESTAMP("Tonemap"); - _render_buffers_post_process_and_tonemap(p_render_buffers, p_environment, p_camera_effects, p_cam_projection); + _render_buffers_post_process_and_tonemap(&render_data); _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) { rb->sdfgi->debug_draw(p_cam_projection, p_cam_transform, rb->width, rb->height, rb->render_target, rb->texture); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 7600d6823e..1f82ae6dec 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -43,6 +43,40 @@ #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" +struct RenderDataRD { + RID render_buffers = RID(); + + Transform cam_transform = Transform(); + CameraMatrix cam_projection = CameraMatrix(); + bool cam_ortogonal = false; + + float z_near = 0.0; + float z_far = 0.0; + + const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr; + const PagedArray<RID> *lights = nullptr; + const PagedArray<RID> *reflection_probes = nullptr; + const PagedArray<RID> *gi_probes = nullptr; + const PagedArray<RID> *decals = nullptr; + const PagedArray<RID> *lightmaps = nullptr; + RID environment = RID(); + RID camera_effects = RID(); + RID shadow_atlas = RID(); + RID reflection_atlas = RID(); + RID reflection_probe = RID(); + int reflection_probe_pass = 0; + + float lod_distance_multiplier = 0.0; + Plane lod_camera_plane = Plane(); + float screen_lod_threshold = 0.0; + + RID cluster_buffer = RID(); + uint32_t cluster_size = 0; + uint32_t cluster_max_elements = 0; + + uint32_t directional_light_count = 0; +}; + class RendererSceneRenderRD : public RendererSceneRender { friend RendererSceneSkyRD; friend RendererSceneGIRD; @@ -62,7 +96,7 @@ protected: void _setup_decals(const PagedArray<RID> &p_decals, const Transform &p_camera_inverse_xform); void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment); - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_cluster_max_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0; + virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0; virtual void _render_shadow_begin() = 0; virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true) = 0; @@ -85,12 +119,11 @@ protected: void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive); void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera); - bool _needs_post_prepass_render(bool p_use_gi); - void _post_prepass_render(bool p_use_gi); - void _pre_resolve_render(bool p_use_gi); + 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(bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer); - uint32_t _get_render_state_directional_light_count() const; + void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_gi, RID p_normal_roughness_buffer, RID p_gi_probe_buffer); // needed for a single argument calls (material and uv2) PagedArrayPool<GeometryInstance *> cull_argument_pool; @@ -445,7 +478,7 @@ private: void _allocate_luminance_textures(RenderBuffers *rb); void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer); - void _render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection); + void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data); /* Cluster */ @@ -592,38 +625,19 @@ private: } cluster; struct RenderState { - RID render_buffers; - Transform cam_transform; - CameraMatrix cam_projection; - bool cam_ortogonal = false; - const PagedArray<GeometryInstance *> *instances = nullptr; - const PagedArray<RID> *lights = nullptr; - const PagedArray<RID> *reflection_probes = nullptr; - const PagedArray<RID> *gi_probes = nullptr; - const PagedArray<RID> *decals = nullptr; - const PagedArray<RID> *lightmaps = nullptr; - RID environment; - RID camera_effects; - RID shadow_atlas; - RID reflection_atlas; - RID reflection_probe; - int reflection_probe_pass = 0; - float screen_lod_threshold = 0.0; - - const RenderShadowData *render_shadows = nullptr; + const RendererSceneRender::RenderShadowData *render_shadows = nullptr; int render_shadow_count = 0; - const RenderSDFGIData *render_sdfgi_regions = nullptr; + const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr; int render_sdfgi_region_count = 0; - const RenderSDFGIUpdateData *sdfgi_update_data = nullptr; + const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr; - uint32_t directional_light_count = 0; uint32_t gi_probe_count = 0; LocalVector<int> cube_shadows; LocalVector<int> shadows; LocalVector<int> directional_shadows; - bool depth_prepass_used; + bool depth_prepass_used; // this does not seem used anywhere... } render_state; struct VolumetricFog { diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 47b9e33ca6..f419875d58 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -3873,6 +3873,18 @@ void RendererStorageRD::particles_initialize(RID p_rid) { particles_owner.initialize_rid(p_rid, Particles()); } +void RendererStorageRD::particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) { + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND(!particles); + if (particles->mode == p_mode) { + return; + } + + _particles_free_data(particles); + + particles->mode = p_mode; +} + void RendererStorageRD::particles_set_emitting(RID p_particles, bool p_emitting) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND(!particles); @@ -4765,7 +4777,7 @@ void RendererStorageRD::particles_set_view_axis(RID p_particles, const Vector3 & copy_push_constant.total_particles *= copy_push_constant.total_particles; RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : (particles->mode == RS::PARTICLES_MODE_2D ? ParticlesShader::COPY_MODE_FILL_INSTANCES_2D : ParticlesShader::COPY_MODE_FILL_INSTANCES)]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); if (do_sort) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_sort_uniform_set, 1); @@ -4785,8 +4797,12 @@ void RendererStorageRD::_particles_update_buffers(Particles *particles) { if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) { total_amount *= particles->trail_bind_poses.size(); } + + uint32_t xform_size = particles->mode == RS::PARTICLES_MODE_2D ? 2 : 3; + particles->particle_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ParticleData) * total_amount); - particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (3 + 1 + 1) * total_amount); + + particles->particle_instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(float) * 4 * (xform_size + 1 + 1) * total_amount); //needs to clear it { @@ -5004,7 +5020,7 @@ void RendererStorageRD::update_particles() { } RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[ParticlesShader::COPY_MODE_FILL_INSTANCES]); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, particles_shader.copy_pipelines[particles->mode == RS::PARTICLES_MODE_2D ? ParticlesShader::COPY_MODE_FILL_INSTANCES_2D : ParticlesShader::COPY_MODE_FILL_INSTANCES]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->particles_copy_uniform_set, 0); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, particles->trail_bind_pose_uniform_set, 2); RD::get_singleton()->compute_list_set_push_constant(compute_list, ©_push_constant, sizeof(ParticlesShader::CopyPushConstant)); @@ -9220,6 +9236,7 @@ RendererStorageRD::RendererStorageRD() { { Vector<String> copy_modes; copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n"); + copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define MODE_2D\n"); copy_modes.push_back("\n#define MODE_FILL_SORT_BUFFER\n#define USE_SORT_BUFFER\n"); copy_modes.push_back("\n#define MODE_FILL_INSTANCES\n#define USE_SORT_BUFFER\n"); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 961bdfb178..49f7f3dba6 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -580,6 +580,7 @@ private: RID buffer; //storage buffer RID uniform_set_3d; + RID uniform_set_2d; bool dirty = false; MultiMesh *dirty_list = nullptr; @@ -696,6 +697,7 @@ private: }; struct Particles { + RS::ParticlesMode mode = RS::PARTICLES_MODE_3D; bool inactive = true; float inactive_time = 0.0; bool emitting = false; @@ -822,6 +824,7 @@ private: enum { COPY_MODE_FILL_INSTANCES, + COPY_MODE_FILL_INSTANCES_2D, COPY_MODE_FILL_SORT_BUFFER, COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER, COPY_MODE_MAX, @@ -1699,6 +1702,21 @@ public: return multimesh->uniform_set_3d; } + _FORCE_INLINE_ RID multimesh_get_2d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + if (!multimesh->uniform_set_2d.is_valid()) { + Vector<RD::Uniform> uniforms; + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(multimesh->buffer); + uniforms.push_back(u); + multimesh->uniform_set_2d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return multimesh->uniform_set_2d; + } + /* IMMEDIATE API */ RID immediate_allocate() { return RID(); } @@ -2093,6 +2111,7 @@ public: RID particles_allocate(); void particles_initialize(RID p_particles_collision); + void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode); void particles_set_emitting(RID p_particles, bool p_emitting); void particles_set_amount(RID p_particles, int p_amount); void particles_set_lifetime(RID p_particles, float p_lifetime); @@ -2137,6 +2156,12 @@ public: virtual bool particles_is_inactive(RID p_particles) const; + _FORCE_INLINE_ RS::ParticlesMode particles_get_mode(RID p_particles) { + Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND_V(!particles, RS::PARTICLES_MODE_2D); + return particles->mode; + } + _FORCE_INLINE_ uint32_t particles_get_amount(RID p_particles, uint32_t &r_trail_divisor) { Particles *particles = particles_owner.getornull(p_particles); ERR_FAIL_COND_V(!particles, 0); diff --git a/servers/rendering/renderer_rd/shaders/blit.glsl b/servers/rendering/renderer_rd/shaders/blit.glsl new file mode 100644 index 0000000000..967da1e6e4 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/blit.glsl @@ -0,0 +1,95 @@ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +layout(push_constant, binding = 0, std140) uniform Pos { + vec4 dst_rect; + + vec2 eye_center; + float k1; + float k2; + + float upscale; + float aspect_ratio; + uint layer; + uint pad1; +} +data; + +layout(location = 0) out vec2 uv; + +void main() { + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + uv = base_arr[gl_VertexIndex]; + vec2 vtx = data.dst_rect.xy + uv * data.dst_rect.zw; + gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0); +} + +#[fragment] + +#version 450 + +#VERSION_DEFINES + +layout(push_constant, binding = 0, std140) uniform Pos { + vec4 dst_rect; + + vec2 eye_center; + float k1; + float k2; + + float upscale; + float aspect_ratio; + uint layer; + uint pad1; +} +data; + +layout(location = 0) in vec2 uv; + +layout(location = 0) out vec4 color; + +#ifdef USE_LAYER +layout(binding = 0) uniform sampler2DArray src_rt; +#else +layout(binding = 0) uniform sampler2D src_rt; +#endif + +void main() { +#ifdef APPLY_LENS_DISTORTION + vec2 coords = uv * 2.0 - 1.0; + vec2 offset = coords - data.eye_center; + + // take aspect ratio into account + offset.y /= data.aspect_ratio; + + // distort + vec2 offset_sq = offset * offset; + float radius_sq = offset_sq.x + offset_sq.y; + float radius_s4 = radius_sq * radius_sq; + float distortion_scale = 1.0 + (data.k1 * radius_sq) + (data.k2 * radius_s4); + offset *= distortion_scale; + + // reapply aspect ratio + offset.y *= data.aspect_ratio; + + // add our eye center back in + coords = offset + data.eye_center; + coords /= data.upscale; + + // and check our color + if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) { + color = vec4(0.0, 0.0, 0.0, 1.0); + } else { + // layer is always used here + coords = (coords + vec2(1.0)) / vec2(2.0); + color = texture(src_rt, vec3(coords, data.layer)); + } +#elif defined(USE_LAYER) + color = texture(src_rt, vec3(uv, data.layer)); +#else + color = texture(src_rt, uv); +#endif +} diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index 8b97ec119f..cf4c77db0d 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -84,40 +84,84 @@ void main() { mat4 world_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0)); -#if 0 - if (draw_data.flags & FLAGS_INSTANCING_ENABLED) { - uint offset = draw_data.flags & FLAGS_INSTANCING_STRIDE_MASK; - offset *= gl_InstanceIndex; - mat4 instance_xform = mat4( - vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), 0.0, texelFetch(instancing_buffer, offset + 3)), - vec4(texelFetch(instancing_buffer, offset + 4), texelFetch(instancing_buffer, offset + 5), 0.0, texelFetch(instancing_buffer, offset + 7)), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(0.0, 0.0, 0.0, 1.0)); - offset += 8; - if (draw_data.flags & FLAGS_INSTANCING_HAS_COLORS) { - vec4 instance_color; - if (draw_data.flags & FLAGS_INSTANCING_COLOR_8_BIT) { - uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset)); - instance_color = unpackUnorm4x8(bits); - offset += 1; - } else { - instance_color = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3)); - offset += 4; - } +#define FLAGS_INSTANCING_MASK 0x7F +#define FLAGS_INSTANCING_HAS_COLORS (1 << 7) +#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 8) + + uint instancing = draw_data.flags & FLAGS_INSTANCING_MASK; + +#ifdef USE_ATTRIBUTES + + if (instancing > 1) { + // trails + + uint stride = 2 + 1 + 1; //particles always uses this format - color *= instance_color; + uint trail_size = instancing; + + uint offset = trail_size * stride * gl_InstanceIndex; + + mat4 matrix; + vec4 pcolor; + { + uint boffset = offset + bone_attrib.x * stride; + matrix = mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.x; + pcolor = transforms.data[boffset + 3] * weight_attrib.x; } - if (draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA) { - if (draw_data.flags & FLAGS_INSTANCING_CUSTOM_DATA_8_BIT) { - uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset)); - instance_custom = unpackUnorm4x8(bits); - } else { - instance_custom = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3)); + if (weight_attrib.y > 0.001) { + uint boffset = offset + bone_attrib.y * stride; + matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.y; + pcolor += transforms.data[boffset + 3] * weight_attrib.y; + } + if (weight_attrib.z > 0.001) { + uint boffset = offset + bone_attrib.z * stride; + matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.z; + pcolor += transforms.data[boffset + 3] * weight_attrib.z; + } + if (weight_attrib.w > 0.001) { + uint boffset = offset + bone_attrib.w * stride; + matrix += mat4(transforms.data[boffset + 0], transforms.data[boffset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weight_attrib.w; + pcolor += transforms.data[boffset + 3] * weight_attrib.w; + } + + instance_custom = transforms.data[offset + 4]; + + color *= pcolor; + + matrix = transpose(matrix); + world_matrix = world_matrix * matrix; + + } else +#endif // USE_ATTRIBUTES + + if (instancing == 1) { + uint stride = 2; + { + if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) { + stride += 1; + } + if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { + stride += 1; } } - } -#endif + uint offset = stride * gl_InstanceIndex; + + mat4 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)); + offset += 2; + + if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) { + color *= transforms.data[offset]; + offset += 1; + } + + if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) { + instance_custom = transforms.data[offset]; + } + + matrix = transpose(matrix); + world_matrix = world_matrix * matrix; + } #if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) if (bool(draw_data.flags & FLAGS_USING_PARTICLES)) { diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index cf7678ea31..451f9b0089 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -5,12 +5,10 @@ #define SDF_MAX_LENGTH 16384.0 -#define FLAGS_INSTANCING_STRIDE_MASK 0xF -#define FLAGS_INSTANCING_ENABLED (1 << 4) -#define FLAGS_INSTANCING_HAS_COLORS (1 << 5) -#define FLAGS_INSTANCING_COLOR_8BIT (1 << 6) -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 7) -#define FLAGS_INSTANCING_CUSTOM_DATA_8_BIT (1 << 8) +//1 means enabled, 2+ means trails in use +#define FLAGS_INSTANCING_MASK 0x7F +#define FLAGS_INSTANCING_HAS_COLORS (1 << 7) +#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 8) #define FLAGS_CLIP_RECT_UV (1 << 9) #define FLAGS_TRANSPOSE_RECT (1 << 10) diff --git a/servers/rendering/renderer_rd/shaders/particles_copy.glsl b/servers/rendering/renderer_rd/shaders/particles_copy.glsl index 7804d66d1c..e2bebadf1a 100644 --- a/servers/rendering/renderer_rd/shaders/particles_copy.glsl +++ b/servers/rendering/renderer_rd/shaders/particles_copy.glsl @@ -163,11 +163,20 @@ void main() { txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); //zero scale, becomes invisible } +#ifdef MODE_2D + + instances.data[write_offset + 0] = txform[0]; + instances.data[write_offset + 1] = txform[1]; + instances.data[write_offset + 2] = particles.data[particle].color; + instances.data[write_offset + 3] = particles.data[particle].custom; + +#else instances.data[write_offset + 0] = txform[0]; instances.data[write_offset + 1] = txform[1]; instances.data[write_offset + 2] = txform[2]; instances.data[write_offset + 3] = particles.data[particle].color; instances.data[write_offset + 4] = particles.data[particle].custom; +#endif //MODE_2D #endif } diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index 669ffc961d..b831005256 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -74,6 +74,53 @@ void main() { #ifdef MODE_2D vec2 vertex = uintBitsToFloat(uvec2(src_vertices.data[src_offset + 0], src_vertices.data[src_offset + 1])); + + if (params.has_blend_shape) { + float blend_total = 0.0; + vec2 blend_vertex = vec2(0.0); + + for (uint i = 0; i < params.blend_shape_count; i++) { + float w = blend_shape_weights.data[i]; + if (abs(w) > 0.0001) { + uint base_offset = (params.vertex_count * i + index) * params.vertex_stride; + + blend_vertex += uintBitsToFloat(uvec2(src_blend_shapes.data[base_offset + 0], src_blend_shapes.data[base_offset + 1])) * w; + + base_offset += 2; + + blend_total += w; + } + } + + if (params.normalized_blend_shapes) { + vertex = (1.0 - blend_total) * vertex; + } + + vertex += blend_vertex; + } + + if (params.has_skeleton) { + uint skin_offset = params.skin_stride * index; + + uvec2 bones = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); + uvec2 bones_01 = uvec2(bones.x & 0xFFFF, bones.x >> 16) * 3; //pre-add xform offset + uvec2 bones_23 = uvec2(bones.y & 0xFFFF, bones.y >> 16) * 3; + + skin_offset += params.skin_weight_offset; + + uvec2 weights = uvec2(src_bone_weights.data[skin_offset + 0], src_bone_weights.data[skin_offset + 1]); + + vec2 weights_01 = unpackUnorm2x16(weights.x); + vec2 weights_23 = unpackUnorm2x16(weights.y); + + mat4 m = mat4(bone_transforms.data[bones_01.x], bone_transforms.data[bones_01.x + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.x; + m += mat4(bone_transforms.data[bones_01.y], bone_transforms.data[bones_01.y + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.y; + m += mat4(bone_transforms.data[bones_23.x], bone_transforms.data[bones_23.x + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x; + m += mat4(bone_transforms.data[bones_23.y], bone_transforms.data[bones_23.y + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y; + + //reverse order because its transposed + vertex = (vec4(vertex, 0.0, 1.0) * m).xy; + } #else vec3 vertex; vec3 normal; diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h index 15d99c038e..cc4ff5d55e 100644 --- a/servers/rendering/renderer_storage.h +++ b/servers/rendering/renderer_storage.h @@ -484,6 +484,7 @@ public: virtual RID particles_allocate() = 0; virtual void particles_initialize(RID p_rid) = 0; + virtual void particles_set_mode(RID p_particles, RS::ParticlesMode p_mode) = 0; virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; virtual bool particles_get_emitting(RID p_particles) = 0; diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 2de0549e8d..d86c44a206 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -93,10 +93,14 @@ public: DeviceFamily device_family = DEVICE_UNKNOWN; uint32_t version_major = 1.0; uint32_t version_minor = 0.0; + // subgroup capabilities uint32_t subgroup_size = 0; uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc. uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations + + // features + bool supports_multiview = false; // If true this device supports multiview options }; typedef Vector<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index c76ae1bb34..bf47d497b6 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -478,6 +478,7 @@ public: FUNCRIDSPLIT(particles) + FUNC2(particles_set_mode, RID, ParticlesMode) FUNC2(particles_set_emitting, RID, bool) FUNC1R(bool, particles_get_emitting, RID) FUNC2(particles_set_amount, RID, int) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 0d6d3f5e13..a81306b97d 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2969,6 +2969,20 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { } } +bool ShaderLanguage::is_control_flow_keyword(String p_keyword) { + return p_keyword == "break" || + p_keyword == "case" || + p_keyword == "continue" || + p_keyword == "default" || + p_keyword == "do" || + p_keyword == "else" || + p_keyword == "for" || + p_keyword == "if" || + p_keyword == "return" || + p_keyword == "switch" || + p_keyword == "while"; +} + void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { Set<String> kws; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 470f3d38d5..e00f4dce19 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -748,6 +748,7 @@ public: static uint32_t get_type_size(DataType p_type); static void get_keyword_list(List<String> *r_keywords); + static bool is_control_flow_keyword(String p_keyword); static void get_builtin_funcs(List<String> *r_keywords); struct BuiltInInfo { diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a9154603ee..49990407e3 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -858,8 +858,10 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa case Variant::PACKED_VECTOR2_ARRAY: { Vector<Vector2> v2 = p_arrays[i]; array_len = v2.size(); + format |= ARRAY_FLAG_USE_2D_VERTICES; } break; case Variant::PACKED_VECTOR3_ARRAY: { + ERR_FAIL_COND_V(p_compress_format & ARRAY_FLAG_USE_2D_VERTICES, ERR_INVALID_PARAMETER); Vector<Vector3> v3 = p_arrays[i]; array_len = v3.size(); } break; diff --git a/servers/rendering_server.h b/servers/rendering_server.h index ad965e9690..0c1a010f73 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -618,6 +618,12 @@ public: virtual RID particles_create() = 0; + enum ParticlesMode { + PARTICLES_MODE_2D, + PARTICLES_MODE_3D + }; + virtual void particles_set_mode(RID p_particles, ParticlesMode p_mode) = 0; + virtual void particles_set_emitting(RID p_particles, bool p_enable) = 0; virtual bool particles_get_emitting(RID p_particles) = 0; virtual void particles_set_amount(RID p_particles, int p_amount) = 0; |