diff options
480 files changed, 20115 insertions, 4402 deletions
@@ -72,6 +72,7 @@ Leon Krause <lk@leonkrause.com> <eska014@users.noreply.github.com> Manuel Strey <manuel.strey@gmx.de> Marcelo Fernandez <marcelofg55@gmail.com> Marcin Zawiejski <dragmz@gmail.com> +Marcus Elg <marcusaccounts@yahoo.se> Mariano Javier Suligoy <marianognu.easyrpg@gmail.com> Mario Schlack <m4r10.5ch14ck@gmail.com> marxin <mliska@suse.cz> diff --git a/.travis.yml b/.travis.yml index 58c3733d22..2639cf9661 100644 --- a/.travis.yml +++ b/.travis.yml @@ -100,7 +100,7 @@ matrix: packages: - *linux_deps - - name: Javascript export template (release, emscripten latest) + - name: JavaScript export template (release, emscripten latest) stage: build env: PLATFORM=javascript TOOLS=no TARGET=release CACHE_NAME=${PLATFORM}-emcc-latest EXTRA_ARGS="use_closure_compiler=yes" os: linux diff --git a/AUTHORS.md b/AUTHORS.md index e8bb91d4bb..f1803c672c 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -110,10 +110,13 @@ name is available. Leon Krause (eska014) Lucien Menassol (Kanabenki) m4nu3lf + Maganty Rushyendra (mrushyendra) Marcel Admiraal (madmiraal) Marcelo Fernandez (marcelofg55) Marc Gilleron (Zylann) Marcin Zawiejski (dragmz) + Marcus Brummer (mbrlabs) + Marcus (MCrafterzz) Mariano Javier Suligoy (MarianoGnu) Mario Schlack (hurikhan) Martin Capitanio (capnm) @@ -25,13 +25,14 @@ generous deed immortalized in the next stable release of Godot Engine. AD Ford Alan Beauchamp albinaask + Alejandro Saucedo Andrew Dunai Brandon Lamb Christian Baune Christopher Montesano - Darius Pranskus Darkhan Baimyrza Darrin Massena + Digital Grows Dov Zimring Edward Flick Gamechuck @@ -42,9 +43,7 @@ generous deed immortalized in the next stable release of Godot Engine. Jasper Brooks Javary Co. Jeffery Chiu - John Benard (Linuxydable) Justin Arnold - Justo Delgado Baudà Kyle Szklenski Marcel Kräml Matthieu Huvé @@ -52,7 +51,6 @@ generous deed immortalized in the next stable release of Godot Engine. Mike King Nathan Warden Neal Gompa (Conan Kudo) - Péter Magyar Ronnie Cheng Slobodan Milnovic Stephan Lanfermann @@ -64,46 +62,51 @@ generous deed immortalized in the next stable release of Godot Engine. Bjarke David Gehrig - David Graham David Snopek Ed Morley Florian Rämisch Jakub Grzesik - HardRound Manuele Finocchiaro Officine Pixel S.n.c. + Rami Ronan Zeegers Sofox + Spicylewd Taylor Ritenour Zaven Muradyan + Andreas Schüle + Andres Hernandez Asher Glick Austen McRae Bernhard Werner beVR Carlo Cabanilla + Christopher Case Daniel James David Giardi Default Name eggs Florian Breisch + Forge Gamejunkey Javier Roman Jon Woodward Karl Werf - Keinan Powers Klavdij Voncina Lex Steers Luke Maciej Pendolski Matthew Hillier Mohamed Ikbel Boulabiar + Monster Vial Rene Retro Village Rob Messick Roland Fredenhagen Ryan Badour Sandro Jenny + Sarksus Scott Wadden Sergey thechris @@ -114,6 +117,7 @@ generous deed immortalized in the next stable release of Godot Engine. Alex Khayrullin alice gambrell + Andrew Harris Barugon Chris Goddard Chris Serino @@ -121,28 +125,31 @@ generous deed immortalized in the next stable release of Godot Engine. Conrad Curry Craig Smith Darrian Little + dragonage13 + GiulianoB Hoai Nam Tran Horváth Péter - Jamal Aboudrar + Jeff Nyte Joan Fons Joshua Flores Leo Fidel R Liban + Michael Dürwald + Péter Magyar Petr Malac - Rami Rob Robert Willes Ronnie Ashlock SKison Thomas Bjarnelöf - Unseen Domains Valryia Vincent Henderson + VojtÄ›ch Wojciech Chojnacki Xavier PATRICELLI + Zoran Kukulj Adam Nakonieczny Adam Neumann - Adrian Demetrescu Alexander J Maynard Alexey Dyadchenko Andreas Funke @@ -152,20 +159,21 @@ generous deed immortalized in the next stable release of Godot Engine. Carlos de Sousa Marques Charlie Whitfield Chase Taranto + Chelsea Hash Chris Petrich Christian Alexander Bjørklund Bøhler Christian Leth Jeppesen - Christoph Schröder - Codee Leaf Cody Parker Craig Ostrin curtis Kramer D + Dev To be curious + Digital Denizen Easypete Edgar Sun - Eric Monson Eugenio Hugo Salgüero Jáñez flesk + F S Gary Hulst gavlig GGGames.org @@ -174,24 +182,27 @@ generous deed immortalized in the next stable release of Godot Engine. Hu Hund Isaac Clausman Jared White - Jeff Nyte Joe Flood John G Gentzel Jose Malheiro + Joseph Crane Joshua Lesperance Juan Velandia Julian Todd Juraj Móza + Justo Delgado Baudà Kelteseth kickmaniac kinfox Lain Ballard + luca duran Marcelo Dornbusch Lopes Marcelo Henrique Gonçalves Markus Fehr Markus Wiesner Martin Eigel Matt Eunson + Mikado069 m kaersten MuffinManKen Nick Abousselam @@ -201,6 +212,7 @@ generous deed immortalized in the next stable release of Godot Engine. Paul Hocker Paul Von Zimmerman Pete Goodwin + PhaineOfCatz pl Ranoller Rob McInroy @@ -208,6 +220,7 @@ generous deed immortalized in the next stable release of Godot Engine. Ryan Samuel Judd Scott Pilet + Scott Ryan-Taylor Sean Morgan Sean Robertson Sébastien @@ -215,6 +228,7 @@ generous deed immortalized in the next stable release of Godot Engine. SleepCircle spilldata Stoned Xander + Tahiti Bos TheLevelOfDetail . Thomas Kurz Tobias Bocanegra @@ -228,7 +242,9 @@ generous deed immortalized in the next stable release of Godot Engine. ## Silver donors 1D_Inc + Aaron Aaron Winter + Abel Crunk Abraham Haskins Acheron Adam @@ -244,18 +260,15 @@ generous deed immortalized in the next stable release of Godot Engine. Agustinus Arya Aidan O'Flannagain Aki Mimoto - Alan Stice Albin Jonasson Svärdsby Alder Stefano AleMax Alessandro Senese Alexander Erlemann alex clavelle - Alfred Reinold Baudisch Allan Davis Allen Schade Andreas Krampitz - Andres Hernandez André Simões andrew james morris Andrew Mansuetti @@ -267,12 +280,12 @@ generous deed immortalized in the next stable release of Godot Engine. Armin Preiml Arseniy M Arthur S. Muszynski - Asger Ashley Claymore Ashton Scott Snapp Aubrey Falconer B A Balázs Batári + Balázs Hasprai Bartosz Bielecki Benedikt Ben Vercammen @@ -299,21 +312,24 @@ generous deed immortalized in the next stable release of Godot Engine. Christoph Woinke Clay Heaton Cole Johnson + Cuauhtemoc Moreno Curt King - Daniel Johnson Daniel Kimblad + Daniel Johnson + DanielMaximiano Daniel Tebbutt + Dave Walker David May David Woodard Dimitri Stanojevic - Dominic Cooney + Dmytro Korchynskyi Dominik Wetzel Donn Eddy Dragontrapper Dr Ewan Murray + Dr.Raccoon Duobix Duodecimal - Dylan Todd Eduardo Teixeira Edward Herbert Edward Swartz @@ -331,11 +347,11 @@ generous deed immortalized in the next stable release of Godot Engine. Fancy Ants Studios Fekinox Felix Bohmann - Felix Kollmann Flaredown + Florian Richer Forty Doubleu - FuDiggity Frank + FuDiggity Gadzhi Kharkharov gamedev by Celio Gary Thomas @@ -347,6 +363,7 @@ generous deed immortalized in the next stable release of Godot Engine. Guillaume Audirac Guillaume Pham Ngoc Guldoman + Gustavo Loureiro dos Reis Hal A Heribert Hirth Hunter Jones @@ -357,12 +374,14 @@ generous deed immortalized in the next stable release of Godot Engine. Ivan Nikolaev Jackson Harmer Jacob + Jaguar Jaiden Gerig Jaime Ruiz-Borau Vizárraga Jako Danar James A F Manley + Jamiee H + Jamie Massey Janders - Jannik Gröger JARKKO PARVIAINEN Jean-Baptiste LEPESME Jeff Hungerford @@ -372,6 +391,7 @@ generous deed immortalized in the next stable release of Godot Engine. Joel Fivat Joel Höglund Joel Setterberg + Johannes Goslar John Gabriel John Walker Jomei Jackson @@ -385,7 +405,6 @@ generous deed immortalized in the next stable release of Godot Engine. Jon Sully Jordy Goodridge Jorge Antunes - Jorge Caballero Jose Aleman Jose C. Rubio Joseph Catrambone @@ -396,6 +415,7 @@ generous deed immortalized in the next stable release of Godot Engine. Julian Murgia June Little JungleRobba + Justin Calleja Justin Hamilton Justin Spedding KaDokta @@ -405,6 +425,7 @@ generous deed immortalized in the next stable release of Godot Engine. Keith Bradner Kent Jofur Kevin McPhillips + Kevin Velasco Kiri Jolly Kjetil Haugland Klagsam @@ -412,10 +433,9 @@ generous deed immortalized in the next stable release of Godot Engine. Kuan Cheang kycho Kyle Appelgate + Kyuppin Laurent Tréguier - Leonard Meagher Leonardo Dimano - Levi Lindsey Lin Chear Linus Lind Lundgren Lionel Gaillard @@ -425,9 +445,14 @@ generous deed immortalized in the next stable release of Godot Engine. Major Haul Malcolm Marco Lardelli + Mark Jad + Mark Krenz Markus Michael Egger + Martin FIbik Martin Holas + Martin Linklater Martin LiÅ¡ka + Martin Trbola Marvin Mathieu Matt Edwards @@ -438,10 +463,7 @@ generous deed immortalized in the next stable release of Godot Engine. Megasploot Melissa Mears mewin - mhilbrunner - Michael Dürwald Michael Haney - Michael Labbe MichaÅ‚ Skwarek Mikael Olsson Mikayla @@ -470,6 +492,8 @@ generous deed immortalized in the next stable release of Godot Engine. Omar Delarosa Oscar Norlander Pan Ip + Parinya Teerakasemsuk + Patrick Dully Patrick Nafarrete Paul Gieske Paul Mason @@ -478,17 +502,20 @@ generous deed immortalized in the next stable release of Godot Engine. Penguin Peter Philip Cohoe + Piotr Góral Point08 pwab Rad Cat Rafa Laguna + Ram Remi Rampin Rémi Verschelde + Reneator Ricardo Alcantara Richard Diss Richard Ivánek Robert Farr (Larington) - Robert Hernandez + Robert Larnach Roger Smith Roland RzÄ…sa Roman Tinkov @@ -496,7 +523,6 @@ generous deed immortalized in the next stable release of Godot Engine. Ronan Ronny Mühle Ryan Groom - Ryan Hentz Sam Edson Samuele Zolfanelli Scott D. Yelich @@ -534,6 +560,7 @@ generous deed immortalized in the next stable release of Godot Engine. Timothy B. MacDonald Title Plinsut Tobbun + Tobias Bradtke Tom Glenn Toni Duran Torgeir Lilleskog @@ -551,13 +578,15 @@ generous deed immortalized in the next stable release of Godot Engine. Victor Vigilant Watch Vincent Cloutier + Vladimir Savin waka nya Wayne Haak werner mendizabal Wiley Thompson Will Wyatt Goodin - Yegor + Yegor Smirnov + YiYin Gu Yuri LaPointe Yuri Sizov Zgegnesh Hemomancer diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 267391c4d6..cb82dc7f8f 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -454,7 +454,7 @@ Dictionary _OS::get_datetime_from_unix_time(int64_t unix_time_val) const { } else { dayno = (unix_time_val - SECS_DAY + 1) / SECS_DAY; dayclock = unix_time_val - dayno * SECS_DAY; - date.weekday = static_cast<OS::Weekday>((dayno - 3) % 7 + 7); + date.weekday = static_cast<OS::Weekday>(((dayno % 7) + 11) % 7); do { year--; dayno += YEARSIZE(year); diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 5c9fb67de4..4bf31aa55f 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -169,7 +169,7 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve for (int i = 0; i < p_breakpoints.size(); i++) { String bp = p_breakpoints[i]; - int sp = bp.find_last(":"); + int sp = bp.rfind(":"); ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format."); singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp)); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 62f600c5e5..9d55e1312e 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -373,6 +373,7 @@ struct RemoteDebugger::VisualProfiler { struct RemoteDebugger::PerformanceProfiler { Object *performance = nullptr; int last_perf_time = 0; + uint64_t last_monitor_modification_time = 0; void toggle(bool p_enable, const Array &p_opts) {} void add(const Array &p_data) {} @@ -386,12 +387,31 @@ struct RemoteDebugger::PerformanceProfiler { return; } last_perf_time = pt; + + Array custom_monitor_names = performance->call("get_custom_monitor_names"); + + uint64_t monitor_modification_time = performance->call("get_monitor_modification_time"); + if (monitor_modification_time > last_monitor_modification_time) { + last_monitor_modification_time = monitor_modification_time; + EngineDebugger::get_singleton()->send_message("performance:profile_names", custom_monitor_names); + } + int max = performance->get("MONITOR_MAX"); Array arr; - arr.resize(max); + arr.resize(max + custom_monitor_names.size()); for (int i = 0; i < max; i++) { arr[i] = performance->call("get_monitor", i); } + + for (int i = 0; i < custom_monitor_names.size(); i++) { + Variant monitor_value = performance->call("get_custom_monitor", custom_monitor_names[i]); + if (!monitor_value.is_num()) { + ERR_PRINT("Value of custom monitor '" + String(custom_monitor_names[i]) + "' is not a number"); + arr[i + max] = Variant(); + } + arr[i + max] = monitor_value; + } + EngineDebugger::get_singleton()->send_message("performance:profile_frame", arr); } diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index faa3a75fda..0ce0042f50 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -225,7 +225,7 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) { uint16_t debug_port = 6007; if (debug_host.find(":") != -1) { - int sep_pos = debug_host.find_last(":"); + int sep_pos = debug_host.rfind(":"); debug_port = debug_host.substr(sep_pos + 1).to_int(); debug_host = debug_host.substr(0, sep_pos); } diff --git a/core/hash_map.h b/core/hash_map.h index 843430d082..10fc931e7a 100644 --- a/core/hash_map.h +++ b/core/hash_map.h @@ -280,13 +280,13 @@ public: const TData &get(const TKey &p_key) const { const TData *res = getptr(p_key); - ERR_FAIL_COND_V(!res, *res); + CRASH_COND_MSG(!res, "Map key not found."); return *res; } TData &get(const TKey &p_key) { TData *res = getptr(p_key); - ERR_FAIL_COND_V(!res, *res); + CRASH_COND_MSG(!res, "Map key not found."); return *res; } diff --git a/core/image.cpp b/core/image.cpp index 45f10625a9..e2f353698f 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -30,6 +30,7 @@ #include "image.h" +#include "core/error_macros.h" #include "core/hash_map.h" #include "core/io/image_loader.h" #include "core/io/resource_loader.h" @@ -1894,8 +1895,10 @@ Vector<uint8_t> Image::get_data() const { } void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format) { - ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH); - ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT); + ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0."); + ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0."); + ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); + ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); int mm = 0; @@ -1914,8 +1917,10 @@ void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_forma } void Image::create(int p_width, int p_height, bool p_use_mipmaps, Format p_format, const Vector<uint8_t> &p_data) { - ERR_FAIL_INDEX(p_width - 1, MAX_WIDTH); - ERR_FAIL_INDEX(p_height - 1, MAX_HEIGHT); + ERR_FAIL_COND_MSG(p_width <= 0, "Image width must be greater than 0."); + ERR_FAIL_COND_MSG(p_height <= 0, "Image height must be greater than 0."); + ERR_FAIL_COND_MSG(p_width > MAX_WIDTH, "Image width cannot be greater than " + itos(MAX_WIDTH) + "."); + ERR_FAIL_COND_MSG(p_height > MAX_HEIGHT, "Image height cannot be greater than " + itos(MAX_HEIGHT) + "."); ERR_FAIL_COND_MSG(p_width * p_height > MAX_PIXELS, "Too many pixels for image, maximum is " + itos(MAX_PIXELS)); int mm; @@ -2629,6 +2634,7 @@ void Image::fill(const Color &c) { ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr; void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr; @@ -3058,6 +3064,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer); ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer); ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer); + ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data"); @@ -3389,6 +3396,11 @@ Error Image::load_webp_from_buffer(const Vector<uint8_t> &p_array) { return _load_from_buffer(p_array, _webp_mem_loader_func); } +Error Image::load_tga_from_buffer(const Vector<uint8_t> &p_array) { + ERR_FAIL_NULL_V_MSG(_tga_mem_loader_func, ERR_UNAVAILABLE, "TGA module was not installed."); + return _load_from_buffer(p_array, _tga_mem_loader_func); +} + void Image::convert_rg_to_ra_rgba8() { ERR_FAIL_COND(format != FORMAT_RGBA8); ERR_FAIL_COND(!data.size()); diff --git a/core/image.h b/core/image.h index 53c203998e..711bf5721c 100644 --- a/core/image.h +++ b/core/image.h @@ -135,6 +135,7 @@ public: static ImageMemLoadFunc _png_mem_loader_func; static ImageMemLoadFunc _jpg_mem_loader_func; static ImageMemLoadFunc _webp_mem_loader_func; + static ImageMemLoadFunc _tga_mem_loader_func; static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels); static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels); @@ -360,6 +361,7 @@ public: Error load_png_from_buffer(const Vector<uint8_t> &p_array); Error load_jpg_from_buffer(const Vector<uint8_t> &p_array); Error load_webp_from_buffer(const Vector<uint8_t> &p_array); + Error load_tga_from_buffer(const Vector<uint8_t> &p_array); void convert_rg_to_ra_rgba8(); void convert_ra_rgba8_to_rg(); diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index f9d2c9067c..534f3e44de 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -865,7 +865,7 @@ String ResourceLoader::_path_remap(const String &p_path, bool *r_translation_rem bool near_match = false; for (int i = 0; i < res_remaps.size(); i++) { - int split = res_remaps[i].find_last(":"); + int split = res_remaps[i].rfind(":"); if (split == -1) { continue; } diff --git a/core/list.h b/core/list.h index 6052a619fb..f850db5241 100644 --- a/core/list.h +++ b/core/list.h @@ -348,7 +348,7 @@ public: * erase an element in the list, by iterator pointing to it. Return true if it was found/erased. */ bool erase(const Element *p_I) { - if (_data) { + if (_data && p_I) { bool ret = _data->erase(p_I); if (_data->size_cache == 0) { diff --git a/core/local_vector.h b/core/local_vector.h index 7f96b25f8b..d97f3330dc 100644 --- a/core/local_vector.h +++ b/core/local_vector.h @@ -45,6 +45,14 @@ private: T *data = nullptr; public: + T *ptr() { + return data; + } + + const T *ptr() const { + return data; + } + _FORCE_INLINE_ void push_back(T p_elem) { if (unlikely(count == capacity)) { if (capacity == 0) { diff --git a/core/math/basis.cpp b/core/math/basis.cpp index df5199b0f9..dd38e25bb1 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -773,7 +773,7 @@ Basis::operator String() const { mtx += ", "; } - mtx += rtos(elements[i][j]); + mtx += rtos(elements[j][i]); //matrix is stored transposed for performance, so print it transposed } } diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 6421606ca2..13a49feb6b 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -1064,7 +1064,7 @@ Error Expression::_get_token(Token &r_token) { if (is_float) { r_token.value = num.to_double(); } else { - r_token.value = num.to_int64(); + r_token.value = num.to_int(); } return OK; diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp index 7eef94c269..7807ab19a7 100644 --- a/core/math/geometry_3d.cpp +++ b/core/math/geometry_3d.cpp @@ -993,6 +993,8 @@ Vector<uint32_t> Geometry3D::generate_edf(const Vector<bool> &p_voxels, const Ve } } + memdelete_arr(work_memory); + return ret; } diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h index 64cd34892e..6bbf518141 100644 --- a/core/math/geometry_3d.h +++ b/core/math/geometry_3d.h @@ -945,6 +945,16 @@ public: return Color(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6); #undef STP } + + _FORCE_INLINE_ static Vector3 octahedron_map_decode(const Vector2 &p_uv) { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + Vector2 f = p_uv * 2.0 - Vector2(1.0, 1.0); + Vector3 n = Vector3(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y)); + float t = CLAMP(-n.z, 0.0, 1.0); + n.x += n.x >= 0 ? -t : t; + n.y += n.y >= 0 ? -t : t; + return n.normalized(); + } }; #endif // GEOMETRY_3D_H diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index dc68c2a9f9..434f6fa300 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -48,8 +48,10 @@ void MainLoop::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_ABOUT); BIND_CONSTANT(NOTIFICATION_CRASH); BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE); - BIND_CONSTANT(NOTIFICATION_APP_RESUMED); - BIND_CONSTANT(NOTIFICATION_APP_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_RESUMED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_IN); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT); ADD_SIGNAL(MethodInfo("on_request_permissions_result", PropertyInfo(Variant::STRING, "permission"), PropertyInfo(Variant::BOOL, "granted"))); }; diff --git a/core/os/main_loop.h b/core/os/main_loop.h index 90790a45a1..2c34cf193c 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -52,8 +52,10 @@ public: NOTIFICATION_WM_ABOUT = 2011, NOTIFICATION_CRASH = 2012, NOTIFICATION_OS_IME_UPDATE = 2013, - NOTIFICATION_APP_RESUMED = 2014, - NOTIFICATION_APP_PAUSED = 2015, + NOTIFICATION_APPLICATION_RESUMED = 2014, + NOTIFICATION_APPLICATION_PAUSED = 2015, + NOTIFICATION_APPLICATION_FOCUS_IN = 2016, + NOTIFICATION_APPLICATION_FOCUS_OUT = 2017, }; virtual void init(); diff --git a/core/os/os.cpp b/core/os/os.cpp index c842be333c..231069fcfb 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -41,6 +41,7 @@ #include <stdarg.h> OS *OS::singleton = nullptr; +uint64_t OS::target_ticks = 0; OS *OS::get_singleton() { return singleton; @@ -468,6 +469,41 @@ void OS::close_midi_inputs() { } } +void OS::add_frame_delay(bool p_can_draw) { + const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay(); + if (frame_delay) { + // Add fixed frame delay to decrease CPU/GPU usage. This doesn't take + // the actual frame time into account. + // Due to the high fluctuation of the actual sleep duration, it's not recommended + // to use this as a FPS limiter. + delay_usec(frame_delay * 1000); + } + + // Add a dynamic frame delay to decrease CPU/GPU usage. This takes the + // previous frame time into account for a smoother result. + uint64_t dynamic_delay = 0; + if (is_in_low_processor_usage_mode() || !p_can_draw) { + dynamic_delay = get_low_processor_usage_mode_sleep_usec(); + } + const int target_fps = Engine::get_singleton()->get_target_fps(); + if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) { + // Override the low processor usage mode sleep delay if the target FPS is lower. + dynamic_delay = MAX(dynamic_delay, (uint64_t)(1000000 / target_fps)); + } + + if (dynamic_delay > 0) { + target_ticks += dynamic_delay; + uint64_t current_ticks = get_ticks_usec(); + + if (current_ticks < target_ticks) { + delay_usec(target_ticks - current_ticks); + } + + current_ticks = get_ticks_usec(); + target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay); + } +} + OS::OS() { void *volatile stack_bottom; diff --git a/core/os/os.h b/core/os/os.h index 04e10518dc..f21c0d4df7 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -43,6 +43,7 @@ class OS { static OS *singleton; + static uint64_t target_ticks; String _execpath; List<String> _cmdline; bool _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. @@ -212,6 +213,8 @@ public: virtual double get_unix_time() const; virtual void delay_usec(uint32_t p_usec) const = 0; + virtual void add_frame_delay(bool p_can_draw); + virtual uint64_t get_ticks_usec() const = 0; uint32_t get_ticks_msec() const; uint64_t get_splash_tick_msec() const; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 5247f6da40..7e96735d67 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -93,7 +93,7 @@ String ProjectSettings::localize_path(const String &p_path) const { } else { memdelete(dir); - int sep = path.find_last("/"); + int sep = path.rfind("/"); if (sep == -1) { return "res://" + path; } diff --git a/core/ustring.cpp b/core/ustring.cpp index 444338d5ae..5d3cf5f1a4 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -1618,49 +1618,7 @@ String::String(const StrRange &p_range) { copy_from(p_range.c_str, p_range.len); } -int String::hex_to_int(bool p_with_prefix) const { - if (p_with_prefix && length() < 3) { - return 0; - } - - const CharType *s = ptr(); - - int sign = s[0] == '-' ? -1 : 1; - - if (sign < 0) { - s++; - } - - if (p_with_prefix) { - if (s[0] != '0' || s[1] != 'x') { - return 0; - } - s += 2; - } - - int hex = 0; - - while (*s) { - CharType c = LOWERCASE(*s); - int n; - if (c >= '0' && c <= '9') { - n = c - '0'; - } else if (c >= 'a' && c <= 'f') { - n = (c - 'a') + 10; - } else { - return 0; - } - - ERR_FAIL_COND_V_MSG(hex > INT32_MAX / 16, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); - hex *= 16; - hex += n; - s++; - } - - return hex * sign; -} - -int64_t String::hex_to_int64(bool p_with_prefix) const { +int64_t String::hex_to_int(bool p_with_prefix) const { if (p_with_prefix && length() < 3) { return 0; } @@ -1692,8 +1650,9 @@ int64_t String::hex_to_int64(bool p_with_prefix) const { } else { return 0; } - - ERR_FAIL_COND_V_MSG(hex > INT64_MAX / 16, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + // Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error + bool overflow = ((hex > INT64_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT64_MAX >> 4) + 1))) || (sign == -1 && hex == (INT64_MAX >> 4) + 1 && c > '0'); + ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); hex *= 16; hex += n; s++; @@ -1702,7 +1661,7 @@ int64_t String::hex_to_int64(bool p_with_prefix) const { return hex * sign; } -int64_t String::bin_to_int64(bool p_with_prefix) const { +int64_t String::bin_to_int(bool p_with_prefix) const { if (p_with_prefix && length() < 3) { return 0; } @@ -1732,8 +1691,9 @@ int64_t String::bin_to_int64(bool p_with_prefix) const { } else { return 0; } - - ERR_FAIL_COND_V_MSG(binary > INT64_MAX / 2, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + // Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error + bool overflow = ((binary > INT64_MAX / 2) && (sign == 1 || (sign == -1 && binary != (INT64_MAX >> 1) + 1))) || (sign == -1 && binary == (INT64_MAX >> 1) + 1 && c > '0'); + ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); binary *= 2; binary += n; s++; @@ -1742,32 +1702,7 @@ int64_t String::bin_to_int64(bool p_with_prefix) const { return binary * sign; } -int String::to_int() const { - if (length() == 0) { - return 0; - } - - int to = (find(".") >= 0) ? find(".") : length(); - - int integer = 0; - int sign = 1; - - for (int i = 0; i < to; i++) { - CharType c = operator[](i); - if (c >= '0' && c <= '9') { - ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + *this + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); - integer *= 10; - integer += c - '0'; - - } else if (integer == 0 && c == '-') { - sign = -sign; - } - } - - return integer * sign; -} - -int64_t String::to_int64() const { +int64_t String::to_int() const { if (length() == 0) { return 0; } @@ -1780,7 +1715,8 @@ int64_t String::to_int64() const { for (int i = 0; i < to; i++) { CharType c = operator[](i); if (c >= '0' && c <= '9') { - ERR_FAIL_COND_V_MSG(integer > INT64_MAX / 10, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8'))); + ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + *this + " as 64-bit integer, provided value is " + (sign == 1 ? "too big." : "too small.")); integer *= 10; integer += c - '0'; @@ -1792,7 +1728,7 @@ int64_t String::to_int64() const { return integer * sign; } -int String::to_int(const char *p_str, int p_len) { +int64_t String::to_int(const char *p_str, int p_len) { int to = 0; if (p_len >= 0) { to = p_len; @@ -1802,13 +1738,14 @@ int String::to_int(const char *p_str, int p_len) { } } - int integer = 0; - int sign = 1; + int64_t integer = 0; + int64_t sign = 1; for (int i = 0; i < to; i++) { char c = p_str[i]; if (c >= '0' && c <= '9') { - ERR_FAIL_COND_V_MSG(integer > INT32_MAX / 10, sign == 1 ? INT32_MAX : INT32_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); + bool overflow = (integer > INT64_MAX / 10) || (integer == INT64_MAX / 10 && ((sign == 1 && c > '7') || (sign == -1 && c > '8'))); + ERR_FAIL_COND_V_MSG(overflow, sign == 1 ? INT64_MAX : INT64_MIN, "Cannot represent " + String(p_str).substr(0, to) + " as integer, provided value is " + (sign == 1 ? "too big." : "too small.")); integer *= 10; integer += c - '0'; @@ -2343,18 +2280,6 @@ String String::substr(int p_from, int p_chars) const { return s; } -int String::find_last(const String &p_str) const { - int pos = -1; - int findfrom = 0; - int findres = -1; - while ((findres = find(p_str, findfrom)) != -1) { - pos = findres; - findfrom = pos + 1; - } - - return pos; -} - int String::find(const String &p_str, int p_from) const { if (p_from < 0) { return -1; @@ -2645,7 +2570,7 @@ int String::rfindn(const String &p_str, int p_from) const { } bool String::ends_with(const String &p_string) const { - int pos = find_last(p_string); + int pos = rfind(p_string); if (pos == -1) { return false; } @@ -3838,7 +3763,7 @@ bool String::is_valid_ip_address() const { continue; } if (n.is_valid_hex_number(false)) { - int nint = n.hex_to_int(false); + int64_t nint = n.hex_to_int(false); if (nint < 0 || nint > 0xffff) { return false; } @@ -3894,7 +3819,7 @@ String String::get_base_dir() const { } } - int sep = MAX(rs.find_last("/"), rs.find_last("\\")); + int sep = MAX(rs.rfind("/"), rs.rfind("\\")); if (sep == -1) { return base; } @@ -3903,7 +3828,7 @@ String String::get_base_dir() const { } String String::get_file() const { - int sep = MAX(find_last("/"), find_last("\\")); + int sep = MAX(rfind("/"), rfind("\\")); if (sep == -1) { return *this; } @@ -3912,8 +3837,8 @@ String String::get_file() const { } String String::get_extension() const { - int pos = find_last("."); - if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) { + int pos = rfind("."); + if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) { return ""; } @@ -4001,8 +3926,8 @@ String String::property_name_encode() const { } String String::get_basename() const { - int pos = find_last("."); - if (pos < 0 || pos < MAX(find_last("/"), find_last("\\"))) { + int pos = rfind("."); + if (pos < 0 || pos < MAX(rfind("/"), rfind("\\"))) { return *this; } diff --git a/core/ustring.h b/core/ustring.h index 5b13a1c704..e745475f11 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -202,7 +202,6 @@ public: int find(const String &p_str, int p_from = 0) const; ///< return <0 if failed int find(const char *p_str, int p_from = 0) const; ///< return <0 if failed int find_char(const CharType &p_char, int p_from = 0) const; ///< return <0 if failed - int find_last(const String &p_str) const; ///< return <0 if failed int findn(const String &p_str, int p_from = 0) const; ///< return <0 if failed, case insensitive int rfind(const String &p_str, int p_from = -1) const; ///< return <0 if failed int rfindn(const String &p_str, int p_from = -1) const; ///< return <0 if failed, case insensitive @@ -245,13 +244,11 @@ public: bool is_numeric() const; double to_double() const; float to_float() const; - int hex_to_int(bool p_with_prefix = true) const; - int to_int() const; - int64_t hex_to_int64(bool p_with_prefix = true) const; - int64_t bin_to_int64(bool p_with_prefix = true) const; - int64_t to_int64() const; - static int to_int(const char *p_str, int p_len = -1); + int64_t hex_to_int(bool p_with_prefix = true) const; + int64_t bin_to_int(bool p_with_prefix = true) const; + int64_t to_int() const; + static int64_t to_int(const char *p_str, int p_len = -1); static double to_double(const char *p_str); static double to_double(const CharType *p_str, const CharType **r_end = nullptr); static int64_t to_int(const CharType *p_str, int p_len = -1, bool p_clamp = false); diff --git a/core/variant.cpp b/core/variant.cpp index 21aaa0fe9e..f6b7e2821a 100644 --- a/core/variant.cpp +++ b/core/variant.cpp @@ -1409,7 +1409,7 @@ Variant::operator int64_t() const { case FLOAT: return _data._float; case STRING: - return operator String().to_int64(); + return operator String().to_int(); default: { return 0; } diff --git a/core/variant_call.cpp b/core/variant_call.cpp index a8beac1e44..308fa3c407 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -244,7 +244,6 @@ struct _VariantCall { VCALL_LOCALMEM3R(String, countn); VCALL_LOCALMEM2R(String, substr); VCALL_LOCALMEM2R(String, find); - VCALL_LOCALMEM1R(String, find_last); VCALL_LOCALMEM2R(String, findn); VCALL_LOCALMEM2R(String, rfind); VCALL_LOCALMEM2R(String, rfindn); @@ -1780,7 +1779,6 @@ void register_variant_methods() { ADDFUNC3R(STRING, INT, String, count, STRING, "what", INT, "from", INT, "to", varray(0, 0)); ADDFUNC3R(STRING, INT, String, countn, STRING, "what", INT, "from", INT, "to", varray(0, 0)); - ADDFUNC1R(STRING, INT, String, find_last, STRING, "what", varray()); ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0)); ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1)); ADDFUNC2R(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1)); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 2c79e2029e..0c9a4a992a 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1786,6 +1786,7 @@ Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { if (r_valid) { *r_valid = true; } + switch (type) { case VECTOR2: { const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem); diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml index 99b566e74f..6b1864b679 100644 --- a/doc/classes/AcceptDialog.xml +++ b/doc/classes/AcceptDialog.xml @@ -67,6 +67,7 @@ <member name="dialog_text" type="String" setter="set_text" getter="get_text" default=""""> The text displayed by the dialog. </member> + <member name="exclusive" type="bool" setter="set_exclusive" getter="is_exclusive" override="true" default="true" /> <member name="title" type="String" setter="set_title" getter="get_title" override="true" default=""Alert!"" /> <member name="transient" type="bool" setter="set_transient" getter="is_transient" override="true" default="true" /> <member name="visible" type="bool" setter="set_visible" getter="is_visible" override="true" default="false" /> diff --git a/doc/classes/CameraEffects.xml b/doc/classes/CameraEffects.xml index ea9ab85b80..7a874d31db 100644 --- a/doc/classes/CameraEffects.xml +++ b/doc/classes/CameraEffects.xml @@ -34,9 +34,9 @@ The length of the transition between the near blur and no-blur area. </member> <member name="override_exposure" type="float" setter="set_override_exposure" getter="get_override_exposure" default="1.0"> - The exposure override value to use. Higher values will result in a brighter scene. Only effective if [member override_exposure_enable] is [code]true[/code]. + The exposure override value to use. Higher values will result in a brighter scene. Only effective if [member override_exposure_enabled] is [code]true[/code]. </member> - <member name="override_exposure_enable" type="bool" setter="set_override_exposure_enabled" getter="is_override_exposure_enabled" default="false"> + <member name="override_exposure_enabled" type="bool" setter="set_override_exposure_enabled" getter="is_override_exposure_enabled" default="false"> If [code]true[/code], overrides the manual or automatic exposure defined in the [Environment] with the value in [member override_exposure]. </member> </members> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index b3a3722836..be361f93f3 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -285,9 +285,9 @@ </return> <argument index="0" name="position" type="Vector2"> </argument> - <argument index="1" name="rotation" type="float"> + <argument index="1" name="rotation" type="float" default="0.0"> </argument> - <argument index="2" name="scale" type="Vector2"> + <argument index="2" name="scale" type="Vector2" default="Vector2( 1, 1 )"> </argument> <description> Sets a custom transform for drawing via components. Anything drawn afterwards will be transformed by this. diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index f8306cbd72..1fb1de2c12 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -44,9 +44,9 @@ </return> <argument index="0" name="mode" type="int" enum="DisplayServer.WindowMode"> </argument> - <argument index="1" name="rect" type="int"> + <argument index="1" name="flags" type="int"> </argument> - <argument index="2" name="arg2" type="Rect2i" default="Rect2i( 0, 0, 0, 0 )"> + <argument index="2" name="rect" type="Rect2i" default="Rect2i( 0, 0, 0, 0 )"> </argument> <description> </description> diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index dbe725f08b..c2c73a8b83 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -204,6 +204,7 @@ </methods> <members> <member name="distraction_free_mode" type="bool" setter="set_distraction_free_mode" getter="is_distraction_free_mode_enabled"> + If [code]true[/code], enables distraction-free mode which hides side docks to increase the space available for the main view. </member> </members> <constants> diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 2fa791a9df..99fe9b4bb5 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -142,6 +142,15 @@ Adds a custom submenu under [b]Project > Tools >[/b] [code]name[/code]. [code]submenu[/code] should be an object of class [PopupMenu]. This submenu should be cleaned up using [code]remove_tool_menu_item(name)[/code]. </description> </method> + <method name="add_translation_parser_plugin"> + <return type="void"> + </return> + <argument index="0" name="parser" type="EditorTranslationParserPlugin"> + </argument> + <description> + Registers a custom translation parser plugin for extracting translatable strings from custom files. + </description> + </method> <method name="apply_changes" qualifiers="virtual"> <return type="void"> </return> @@ -464,6 +473,15 @@ Removes a menu [code]name[/code] from [b]Project > Tools[/b]. </description> </method> + <method name="remove_translation_parser_plugin"> + <return type="void"> + </return> + <argument index="0" name="parser" type="EditorTranslationParserPlugin"> + </argument> + <description> + Removes a registered custom translation parser plugin. + </description> + </method> <method name="save_external_data" qualifiers="virtual"> <return type="void"> </return> diff --git a/doc/classes/EditorTranslationParserPlugin.xml b/doc/classes/EditorTranslationParserPlugin.xml new file mode 100644 index 0000000000..73098efd99 --- /dev/null +++ b/doc/classes/EditorTranslationParserPlugin.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="EditorTranslationParserPlugin" inherits="Reference" version="4.0"> + <brief_description> + Plugin for adding custom parsers to extract strings that are to be translated from custom files (.csv, .json etc.). + </brief_description> + <description> + Plugins are registered via [method EditorPlugin.add_translation_parser_plugin] method. To define the parsing and string extraction logic, override the [method parse_text] method in script. + The extracted strings will be written into a POT file selected by user under "POT Generation" in "Localization" tab in "Project Settings" menu. + Below shows an example of a custom parser that extracts strings in a CSV file to write into a POT. + [codeblock] + tool + extends EditorTranslationParserPlugin + + func parse_text(text, extracted_strings): + var split_strs = text.split(",", false, 0) + for s in split_strs: + extracted_strings.append(s) + #print("Extracted string: " + s) + + func get_recognized_extensions(): + return ["csv"] + [/codeblock] + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_recognized_extensions" qualifiers="virtual"> + <return type="Array"> + </return> + <description> + Gets the list of file extensions to associate with this parser, e.g. [code]["csv"][/code]. + </description> + </method> + <method name="parse_text" qualifiers="virtual"> + <return type="void"> + </return> + <argument index="0" name="text" type="String"> + </argument> + <argument index="1" name="extracted_strings" type="Array"> + </argument> + <description> + Override this method to define a custom parsing logic to extract the translatable strings. + </description> + </method> + </methods> + <constants> + </constants> +</class> diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml index 3642d92771..bbab0bf8cf 100644 --- a/doc/classes/Environment.xml +++ b/doc/classes/Environment.xml @@ -24,7 +24,7 @@ Returns [code]true[/code] if the glow level [code]idx[/code] is specified, [code]false[/code] otherwise. </description> </method> - <method name="set_glow_level"> + <method name="set_glow_level_enabled"> <return type="void"> </return> <argument index="0" name="idx" type="int"> @@ -46,7 +46,7 @@ <member name="adjustment_contrast" type="float" setter="set_adjustment_contrast" getter="get_adjustment_contrast" default="1.0"> The global contrast value of the rendered scene (default value is 1). Effective only if [code]adjustment_enabled[/code] is [code]true[/code]. </member> - <member name="adjustment_enabled" type="bool" setter="set_adjustment_enable" getter="is_adjustment_enabled" default="false"> + <member name="adjustment_enabled" type="bool" setter="set_adjustment_enabled" getter="is_adjustment_enabled" default="false"> If [code]true[/code], enables the [code]adjustment_*[/code] properties provided by this resource. If [code]false[/code], modifications to the [code]adjustment_*[/code] properties will have no effect on the rendered scene. </member> <member name="adjustment_saturation" type="float" setter="set_adjustment_saturation" getter="get_adjustment_saturation" default="1.0"> @@ -65,7 +65,7 @@ </member> <member name="ambient_light_source" type="int" setter="set_ambient_source" getter="get_ambient_source" enum="Environment.AmbientSource" default="0"> </member> - <member name="auto_exposure_enabled" type="bool" setter="set_tonemap_auto_exposure" getter="get_tonemap_auto_exposure" default="false"> + <member name="auto_exposure_enabled" type="bool" setter="set_tonemap_auto_exposure_enabled" getter="is_tonemap_auto_exposure_enabled" default="false"> If [code]true[/code], enables the tonemapping auto exposure mode of the scene renderer. If [code]true[/code], the renderer will automatically determine the exposure setting to adapt to the scene's illumination and the observed light. </member> <member name="auto_exposure_max_luma" type="float" setter="set_tonemap_auto_exposure_max" getter="get_tonemap_auto_exposure_max" default="8.0"> @@ -158,25 +158,25 @@ <member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity" default="0.8"> The glow intensity. When using the GLES2 renderer, this should be increased to 1.5 to compensate for the lack of HDR rendering. </member> - <member name="glow_levels/1" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false"> + <member name="glow_levels/1" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false"> If [code]true[/code], the 1st level of glow is enabled. This is the most "local" level (least blurry). </member> - <member name="glow_levels/2" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false"> + <member name="glow_levels/2" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false"> If [code]true[/code], the 2th level of glow is enabled. </member> - <member name="glow_levels/3" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="true"> + <member name="glow_levels/3" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="true"> If [code]true[/code], the 3th level of glow is enabled. </member> - <member name="glow_levels/4" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false"> + <member name="glow_levels/4" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false"> If [code]true[/code], the 4th level of glow is enabled. </member> - <member name="glow_levels/5" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="true"> + <member name="glow_levels/5" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="true"> If [code]true[/code], the 5th level of glow is enabled. </member> - <member name="glow_levels/6" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false"> + <member name="glow_levels/6" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false"> If [code]true[/code], the 6th level of glow is enabled. </member> - <member name="glow_levels/7" type="bool" setter="set_glow_level" getter="is_glow_level_enabled" default="false"> + <member name="glow_levels/7" type="bool" setter="set_glow_level_enabled" getter="is_glow_level_enabled" default="false"> If [code]true[/code], the 7th level of glow is enabled. This is the most "global" level (blurriest). </member> <member name="glow_mix" type="float" setter="set_glow_mix" getter="get_glow_mix" default="0.05"> @@ -186,6 +186,30 @@ </member> <member name="reflected_light_source" type="int" setter="set_reflection_source" getter="get_reflection_source" enum="Environment.ReflectionSource" default="0"> </member> + <member name="sdfgi_cascade0_distance" type="float" setter="set_sdfgi_cascade0_distance" getter="get_sdfgi_cascade0_distance" default="12.8"> + </member> + <member name="sdfgi_cascades" type="int" setter="set_sdfgi_cascades" getter="get_sdfgi_cascades" enum="Environment.SDFGICascades" default="1"> + </member> + <member name="sdfgi_enabled" type="bool" setter="set_sdfgi_enabled" getter="is_sdfgi_enabled" default="false"> + </member> + <member name="sdfgi_energy" type="float" setter="set_sdfgi_energy" getter="get_sdfgi_energy" default="1.0"> + </member> + <member name="sdfgi_max_distance" type="float" setter="set_sdfgi_max_distance" getter="get_sdfgi_max_distance" default="819.2"> + </member> + <member name="sdfgi_min_cell_size" type="float" setter="set_sdfgi_min_cell_size" getter="get_sdfgi_min_cell_size" default="0.2"> + </member> + <member name="sdfgi_normal_bias" type="float" setter="set_sdfgi_normal_bias" getter="get_sdfgi_normal_bias" default="1.1"> + </member> + <member name="sdfgi_probe_bias" type="float" setter="set_sdfgi_probe_bias" getter="get_sdfgi_probe_bias" default="1.1"> + </member> + <member name="sdfgi_read_sky_light" type="bool" setter="set_sdfgi_read_sky_light" getter="is_sdfgi_reading_sky_light" default="false"> + </member> + <member name="sdfgi_use_multi_bounce" type="bool" setter="set_sdfgi_use_multi_bounce" getter="is_sdfgi_using_multi_bounce" default="false"> + </member> + <member name="sdfgi_use_occlusion" type="bool" setter="set_sdfgi_use_occlusion" getter="is_sdfgi_using_occlusion" default="false"> + </member> + <member name="sdfgi_y_scale" type="int" setter="set_sdfgi_y_scale" getter="get_sdfgi_y_scale" enum="Environment.SDFGIYScale" default="0"> + </member> <member name="sky" type="Sky" setter="set_sky" getter="get_sky"> The [Sky] resource used for this [Environment]. </member> @@ -285,6 +309,18 @@ <constant name="REFLECTION_SOURCE_SKY" value="2" enum="ReflectionSource"> Use the [Sky] for reflections regardless of what the background is. </constant> + <constant name="TONE_MAPPER_LINEAR" value="0" enum="ToneMapper"> + Linear tonemapper operator. Reads the linear data and passes it on unmodified. + </constant> + <constant name="TONE_MAPPER_REINHARDT" value="1" enum="ToneMapper"> + Reinhardt tonemapper operator. Performs a variation on rendered pixels' colors by this formula: [code]color = color / (1 + color)[/code]. + </constant> + <constant name="TONE_MAPPER_FILMIC" value="2" enum="ToneMapper"> + Filmic tonemapper operator. + </constant> + <constant name="TONE_MAPPER_ACES" value="3" enum="ToneMapper"> + Academy Color Encoding System tonemapper operator. + </constant> <constant name="GLOW_BLEND_MODE_ADDITIVE" value="0" enum="GlowBlendMode"> Additive glow blending mode. Mostly used for particles, glows (bloom), lens flare, bright sources. </constant> @@ -300,18 +336,6 @@ <constant name="GLOW_BLEND_MODE_MIX" value="4" enum="GlowBlendMode"> Mixes the glow with the underlying color to avoid increasing brightness as much while still maintaining a glow effect. </constant> - <constant name="TONE_MAPPER_LINEAR" value="0" enum="ToneMapper"> - Linear tonemapper operator. Reads the linear data and passes it on unmodified. - </constant> - <constant name="TONE_MAPPER_REINHARDT" value="1" enum="ToneMapper"> - Reinhardt tonemapper operator. Performs a variation on rendered pixels' colors by this formula: [code]color = color / (1 + color)[/code]. - </constant> - <constant name="TONE_MAPPER_FILMIC" value="2" enum="ToneMapper"> - Filmic tonemapper operator. - </constant> - <constant name="TONE_MAPPER_ACES" value="3" enum="ToneMapper"> - Academy Color Encoding System tonemapper operator. - </constant> <constant name="SSAO_BLUR_DISABLED" value="0" enum="SSAOBlur"> No blur for the screen-space ambient occlusion effect (fastest). </constant> @@ -324,5 +348,17 @@ <constant name="SSAO_BLUR_3x3" value="3" enum="SSAOBlur"> 3×3 blur for the screen-space ambient occlusion effect. Increases the radius of the blur for a smoother look, but can result in checkerboard-like artifacts. </constant> + <constant name="SDFGI_CASCADES_4" value="0" enum="SDFGICascades"> + </constant> + <constant name="SDFGI_CASCADES_6" value="1" enum="SDFGICascades"> + </constant> + <constant name="SDFGI_CASCADES_8" value="2" enum="SDFGICascades"> + </constant> + <constant name="SDFGI_Y_SCALE_DISABLED" value="0" enum="SDFGIYScale"> + </constant> + <constant name="SDFGI_Y_SCALE_75_PERCENT" value="1" enum="SDFGIYScale"> + </constant> + <constant name="SDFGI_Y_SCALE_50_PERCENT" value="2" enum="SDFGIYScale"> + </constant> </constants> </class> diff --git a/doc/classes/FileSystemDock.xml b/doc/classes/FileSystemDock.xml index fdf29f89b2..c553f90e37 100644 --- a/doc/classes/FileSystemDock.xml +++ b/doc/classes/FileSystemDock.xml @@ -10,11 +10,11 @@ <method name="can_drop_data_fw" qualifiers="const"> <return type="bool"> </return> - <argument index="0" name="arg0" type="Vector2"> + <argument index="0" name="position" type="Vector2"> </argument> - <argument index="1" name="arg1" type="Variant"> + <argument index="1" name="data" type="Variant"> </argument> - <argument index="2" name="arg2" type="Control"> + <argument index="2" name="from" type="Control"> </argument> <description> </description> @@ -22,11 +22,11 @@ <method name="drop_data_fw"> <return type="void"> </return> - <argument index="0" name="arg0" type="Vector2"> + <argument index="0" name="position" type="Vector2"> </argument> - <argument index="1" name="arg1" type="Variant"> + <argument index="1" name="data" type="Variant"> </argument> - <argument index="2" name="arg2" type="Control"> + <argument index="2" name="from" type="Control"> </argument> <description> </description> @@ -34,9 +34,9 @@ <method name="get_drag_data_fw"> <return type="Variant"> </return> - <argument index="0" name="arg0" type="Vector2"> + <argument index="0" name="position" type="Vector2"> </argument> - <argument index="1" name="arg1" type="Control"> + <argument index="1" name="from" type="Control"> </argument> <description> </description> @@ -44,7 +44,7 @@ <method name="navigate_to_path"> <return type="void"> </return> - <argument index="0" name="arg0" type="String"> + <argument index="0" name="path" type="String"> </argument> <description> </description> diff --git a/doc/classes/GIProbe.xml b/doc/classes/GIProbe.xml index 23dd562653..8885f360a3 100644 --- a/doc/classes/GIProbe.xml +++ b/doc/classes/GIProbe.xml @@ -19,7 +19,7 @@ <argument index="1" name="create_visual_debug" type="bool" default="false"> </argument> <description> - Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_INDIRECT] or [constant Light3D.BAKE_ALL]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [GIProbe]'s data and debug any issues that may be occurring. + Bakes the effect from all [GeometryInstance3D]s marked with [constant GeometryInstance3D.GI_MODE_BAKED] and [Light3D]s marked with either [constant Light3D.BAKE_DYNAMIC] or [constant Light3D.BAKE_STATIC]. If [code]create_visual_debug[/code] is [code]true[/code], after baking the light, this will generate a [MultiMesh] that has a cube representing each solid cell with each cube colored to the cell's albedo color. This can be used to visualize the [GIProbe]'s data and debug any issues that may be occurring. </description> </method> <method name="debug_bake"> diff --git a/doc/classes/Geometry2D.xml b/doc/classes/Geometry2D.xml index ffd4bd108d..86dc8e864a 100644 --- a/doc/classes/Geometry2D.xml +++ b/doc/classes/Geometry2D.xml @@ -200,6 +200,13 @@ Inflates or deflates [code]polygon[/code] by [code]delta[/code] units (pixels). If [code]delta[/code] is positive, makes the polygon grow outward. If [code]delta[/code] is negative, shrinks the polygon inward. Returns an array of polygons because inflating/deflating may result in multiple discrete polygons. Returns an empty array if [code]delta[/code] is negative and the absolute value of it approximately exceeds the minimum bounding rectangle dimensions of the polygon. Each polygon's vertices will be rounded as determined by [code]join_type[/code], see [enum PolyJoinType]. The operation may result in an outer polygon (boundary) and inner polygon (hole) produced which could be distinguished by calling [method is_polygon_clockwise]. + [b]Note:[/b] To translate the polygon's vertices specifically, use the [method Transform2D.xform] method: + [codeblock] + var polygon = PackedVector2Array([Vector2(0, 0), Vector2(100, 0), Vector2(100, 100), Vector2(0, 100)]) + var offset = Vector2(50, 50) + polygon = Transform2D(0, offset).xform(polygon) + print(polygon) # prints [Vector2(50, 50), Vector2(150, 50), Vector2(150, 150), Vector2(50, 150)] + [/codeblock] </description> </method> <method name="offset_polyline"> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index d29fcfd96f..5aa5de1dae 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -364,6 +364,15 @@ Loads an image from the binary contents of a PNG file. </description> </method> + <method name="load_tga_from_buffer"> + <return type="int" enum="Error"> + </return> + <argument index="0" name="buffer" type="PackedByteArray"> + </argument> + <description> + Loads an image from the binary contents of a TGA file. + </description> + </method> <method name="load_webp_from_buffer"> <return type="int" enum="Error"> </return> diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index dda6faa80a..6979efa569 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -148,12 +148,9 @@ Light is ignored when baking. [b]Note:[/b] Hiding a light does [i]not[/i] affect baking. </constant> - <constant name="BAKE_INDIRECT" value="1" enum="BakeMode"> - Only indirect lighting will be baked (default). + <constant name="BAKE_DYNAMIC" value="1" enum="BakeMode"> </constant> - <constant name="BAKE_ALL" value="2" enum="BakeMode"> - Both direct and indirect light will be baked. - [b]Note:[/b] You should hide the light if you don't want it to appear twice (dynamic and baked). + <constant name="BAKE_STATIC" value="2" enum="BakeMode"> </constant> </constants> </class> diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml index 7bb478fce2..55ae54d12b 100644 --- a/doc/classes/MainLoop.xml +++ b/doc/classes/MainLoop.xml @@ -142,13 +142,21 @@ Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string). Specific to the macOS platform. </constant> - <constant name="NOTIFICATION_APP_RESUMED" value="2014"> - Notification received from the OS when the app is resumed. + <constant name="NOTIFICATION_APPLICATION_RESUMED" value="2014"> + Notification received from the OS when the application is resumed. Specific to the Android platform. </constant> - <constant name="NOTIFICATION_APP_PAUSED" value="2015"> - Notification received from the OS when the app is paused. + <constant name="NOTIFICATION_APPLICATION_PAUSED" value="2015"> + Notification received from the OS when the application is paused. Specific to the Android platform. </constant> + <constant name="NOTIFICATION_APPLICATION_FOCUS_IN" value="2016"> + Notification received from the OS when the application is focused, i.e. when changing the focus from the OS desktop or a thirdparty application to any open window of the Godot instance. + Implemented on desktop platforms. + </constant> + <constant name="NOTIFICATION_APPLICATION_FOCUS_OUT" value="2017"> + Notification received from the OS when the application is defocused, i.e. when changing the focus from any open window of the Godot instance to the OS desktop or a thirdparty application. + Implemented on desktop platforms. + </constant> </constants> </class> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 9617ee0437..e921cbd58a 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -926,13 +926,11 @@ Notification received from the OS when the mouse leaves the game window. Implemented on desktop and web platforms. </constant> - <constant name="NOTIFICATION_WM_FOCUS_IN" value="1004"> - Notification received from the OS when the game window is focused. - Implemented on all platforms. + <constant name="NOTIFICATION_WM_WINDOW_FOCUS_IN" value="1004"> + Notification received from the OS when the node's parent [Window] is focused. This may be a change of focus between two windows of the same engine instance, or from the OS desktop or a third-party application to a window of the game (in which case [constant NOTIFICATION_APPLICATION_FOCUS_IN] is also emitted). </constant> - <constant name="NOTIFICATION_WM_FOCUS_OUT" value="1005"> - Notification received from the OS when the game window is unfocused. - Implemented on all platforms. + <constant name="NOTIFICATION_WM_WINDOW_FOCUS_OUT" value="1005"> + Notification received from the OS when the node's parent [Window] is defocused. This may be a change of focus between two windows of the same engine instance, or from a window of the game to the OS desktop or a third-party application (in which case [constant NOTIFICATION_APPLICATION_FOCUS_OUT] is also emitted). </constant> <constant name="NOTIFICATION_WM_CLOSE_REQUEST" value="1006"> Notification received from the OS when a close request is sent (e.g. closing the window with a "Close" button or [kbd]Alt + F4[/kbd]). @@ -963,14 +961,22 @@ Notification received from the OS when an update of the Input Method Engine occurs (e.g. change of IME cursor position or composition string). Specific to the macOS platform. </constant> - <constant name="NOTIFICATION_APP_RESUMED" value="2014"> - Notification received from the OS when the app is resumed. + <constant name="NOTIFICATION_APPLICATION_RESUMED" value="2014"> + Notification received from the OS when the application is resumed. Specific to the Android platform. </constant> - <constant name="NOTIFICATION_APP_PAUSED" value="2015"> - Notification received from the OS when the app is paused. + <constant name="NOTIFICATION_APPLICATION_PAUSED" value="2015"> + Notification received from the OS when the application is paused. Specific to the Android platform. </constant> + <constant name="NOTIFICATION_APPLICATION_FOCUS_IN" value="2016"> + Notification received from the OS when the application is focused, i.e. when changing the focus from the OS desktop or a thirdparty application to any open window of the Godot instance. + Implemented on desktop platforms. + </constant> + <constant name="NOTIFICATION_APPLICATION_FOCUS_OUT" value="2017"> + Notification received from the OS when the application is defocused, i.e. when changing the focus from any open window of the Godot instance to the OS desktop or a thirdparty application. + Implemented on desktop platforms. + </constant> <constant name="PAUSE_MODE_INHERIT" value="0" enum="PauseMode"> Inherits pause mode from the node's parent. For the root node, it is equivalent to [constant PAUSE_MODE_STOP]. Default. </constant> diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml index 2a0c153267..0a9079ce71 100644 --- a/doc/classes/Performance.xml +++ b/doc/classes/Performance.xml @@ -5,12 +5,55 @@ </brief_description> <description> This class provides access to a number of different monitors related to performance, such as memory usage, draw calls, and FPS. These are the same as the values displayed in the [b]Monitor[/b] tab in the editor's [b]Debugger[/b] panel. By using the [method get_monitor] method of this class, you can access this data from your code. + You can add custom monitors using the [method add_custom_monitor] method. Custom monitors are available in [b]Monitor[/b] tab in the editor's [b]Debugger[/b] panel together with built-in monitors. [b]Note:[/b] A few of these monitors are only available in debug mode and will always return 0 when used in a release build. [b]Note:[/b] Many of these monitors are not updated in real-time, so there may be a short delay between changes. + [b]Note:[/b] Custom monitors do not support negative values. Negative values are clamped to 0. </description> <tutorials> </tutorials> <methods> + <method name="add_custom_monitor"> + <return type="void"> + </return> + <argument index="0" name="id" type="StringName"> + </argument> + <argument index="1" name="callable" type="Callable"> + </argument> + <argument index="2" name="arguments" type="Array" default="[ ]"> + </argument> + <description> + Adds a custom monitor with name same as id. You can specify the category of monitor using '/' in id. If there are more than one '/' then default category is used. Default category is "Custom". + [codeblock] + Performance.add_custom_monitor("MyCategory/MyMonitor", some_callable) # Adds monitor with name "MyName" to category "MyCategory" + Performance.add_custom_monitor("MyMonitor", some_callable) # Adds monitor with name "MyName" to category "Custom" + # Note: "MyCategory/MyMonitor" and "MyMonitor" have same name but different ids so above code is valid + Performance.add_custom_monitor("Custom/MyMonitor", some_callable) # Adds monitor with name "MyName" to category "Custom" + # Note: "MyMonitor" and "Custom/MyMonitor" have same name and same category but different ids so above code is valid + Performance.add_custom_monitor("MyCategoryOne/MyCategoryTwo/MyMonitor", some_callable) # Adds monitor with name "MyCategoryOne/MyCategoryTwo/MyMonitor" to category "Custom" + [/codeblock] + The debugger calls the callable to get the value of custom monitor. The callable must return a number. + Callables are called with arguments supplied in argument array. + [b]Note:[/b] It throws an error if given id is already present. + </description> + </method> + <method name="get_custom_monitor"> + <return type="Variant"> + </return> + <argument index="0" name="id" type="StringName"> + </argument> + <description> + Returns the value of custom monitor with given id. The callable is called to get the value of custom monitor. + [b]Note:[/b] It throws an error if the given id is absent. + </description> + </method> + <method name="get_custom_monitor_names"> + <return type="Array"> + </return> + <description> + Returns the names of active custom monitors in an array. + </description> + </method> <method name="get_monitor" qualifiers="const"> <return type="float"> </return> @@ -23,6 +66,32 @@ [/codeblock] </description> </method> + <method name="get_monitor_modification_time"> + <return type="int"> + </return> + <description> + Returns the last tick in which custom monitor was added/removed. + </description> + </method> + <method name="has_custom_monitor"> + <return type="bool"> + </return> + <argument index="0" name="id" type="StringName"> + </argument> + <description> + Returns true if custom monitor with the given id is present otherwise returns false. + </description> + </method> + <method name="remove_custom_monitor"> + <return type="void"> + </return> + <argument index="0" name="id" type="StringName"> + </argument> + <description> + Removes the custom monitor with given id. + [b]Note:[/b] It throws an error if the given id is already absent. + </description> + </method> </methods> <constants> <constant name="TIME_FPS" value="0" enum="Monitor"> diff --git a/doc/classes/PhysicalBone3D.xml b/doc/classes/PhysicalBone3D.xml index 58930aae37..0808e4a724 100644 --- a/doc/classes/PhysicalBone3D.xml +++ b/doc/classes/PhysicalBone3D.xml @@ -18,9 +18,9 @@ <method name="apply_impulse"> <return type="void"> </return> - <argument index="0" name="position" type="Vector3"> + <argument index="0" name="impulse" type="Vector3"> </argument> - <argument index="1" name="impulse" type="Vector3"> + <argument index="1" name="position" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> </description> diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml index 46205fecd1..30519e11be 100644 --- a/doc/classes/PhysicsDirectBodyState2D.xml +++ b/doc/classes/PhysicsDirectBodyState2D.xml @@ -22,9 +22,9 @@ <method name="add_force"> <return type="void"> </return> - <argument index="0" name="offset" type="Vector2"> + <argument index="0" name="force" type="Vector2"> </argument> - <argument index="1" name="force" type="Vector2"> + <argument index="1" name="position" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> Adds a positioned force to the body. Both the force and the offset from the body origin are in global coordinates. @@ -51,9 +51,9 @@ <method name="apply_impulse"> <return type="void"> </return> - <argument index="0" name="offset" type="Vector2"> + <argument index="0" name="impulse" type="Vector2"> </argument> - <argument index="1" name="impulse" type="Vector2"> + <argument index="1" name="position" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> Applies a positioned impulse to the body. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason, it should only be used when simulating one-time impacts (use the "_force" functions otherwise). The offset uses the rotation of the global coordinate system, but is centered at the object's origin. diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml index 1ee520fe5f..eea681e696 100644 --- a/doc/classes/PhysicsDirectBodyState3D.xml +++ b/doc/classes/PhysicsDirectBodyState3D.xml @@ -12,7 +12,7 @@ <method name="add_central_force"> <return type="void"> </return> - <argument index="0" name="force" type="Vector3"> + <argument index="0" name="force" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> Adds a constant directional force without affecting rotation. @@ -24,7 +24,7 @@ </return> <argument index="0" name="force" type="Vector3"> </argument> - <argument index="1" name="position" type="Vector3"> + <argument index="1" name="position" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> Adds a positioned force to the body. Both the force and the offset from the body origin are in global coordinates. @@ -42,7 +42,7 @@ <method name="apply_central_impulse"> <return type="void"> </return> - <argument index="0" name="j" type="Vector3"> + <argument index="0" name="impulse" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> Applies a single directional impulse without affecting rotation. @@ -52,9 +52,9 @@ <method name="apply_impulse"> <return type="void"> </return> - <argument index="0" name="position" type="Vector3"> + <argument index="0" name="impulse" type="Vector3"> </argument> - <argument index="1" name="j" type="Vector3"> + <argument index="1" name="position" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> Applies a positioned impulse to the body. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason it should only be used when simulating one-time impacts. The position uses the rotation of the global coordinate system, but is centered at the object's origin. @@ -63,7 +63,7 @@ <method name="apply_torque_impulse"> <return type="void"> </return> - <argument index="0" name="j" type="Vector3"> + <argument index="0" name="impulse" type="Vector3"> </argument> <description> Apply a torque impulse (which will be affected by the body mass and shape). This will rotate the body around the vector [code]j[/code] passed as parameter. diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index d7821b1045..b2904c6538 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -331,9 +331,9 @@ </return> <argument index="0" name="body" type="RID"> </argument> - <argument index="1" name="offset" type="Vector2"> + <argument index="1" name="force" type="Vector2"> </argument> - <argument index="2" name="force" type="Vector2"> + <argument index="2" name="position" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> Adds a positioned force to the applied force and torque. As with [method body_apply_impulse], both the force and the offset from the body origin are in global coordinates. A force differs from an impulse in that, while the two are forces, the impulse clears itself after being applied. @@ -379,9 +379,9 @@ </return> <argument index="0" name="body" type="RID"> </argument> - <argument index="1" name="position" type="Vector2"> + <argument index="1" name="impulse" type="Vector2"> </argument> - <argument index="2" name="impulse" type="Vector2"> + <argument index="2" name="position" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> Adds a positioned impulse to the applied force and torque. Both the force and the offset from the body origin are in global coordinates. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index e9e1552c92..5fd3ef5db2 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -334,7 +334,7 @@ </argument> <argument index="1" name="force" type="Vector3"> </argument> - <argument index="2" name="position" type="Vector3"> + <argument index="2" name="position" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> </description> @@ -379,9 +379,9 @@ </return> <argument index="0" name="body" type="RID"> </argument> - <argument index="1" name="position" type="Vector3"> + <argument index="1" name="impulse" type="Vector3"> </argument> - <argument index="2" name="impulse" type="Vector3"> + <argument index="2" name="position" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> Gives the body a push at a [code]position[/code] in the direction of the [code]impulse[/code]. diff --git a/doc/classes/PhysicsShapeQueryParameters2D.xml b/doc/classes/PhysicsShapeQueryParameters2D.xml index 9a162dabbb..63e13954ab 100644 --- a/doc/classes/PhysicsShapeQueryParameters2D.xml +++ b/doc/classes/PhysicsShapeQueryParameters2D.xml @@ -9,15 +9,6 @@ <tutorials> </tutorials> <methods> - <method name="set_shape"> - <return type="void"> - </return> - <argument index="0" name="shape" type="Resource"> - </argument> - <description> - Sets the [Shape2D] that will be used for collision/intersection queries. - </description> - </method> </methods> <members> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> @@ -38,8 +29,24 @@ <member name="motion" type="Vector2" setter="set_motion" getter="get_motion" default="Vector2( 0, 0 )"> The motion of the shape being queried for. </member> + <member name="shape" type="Resource" setter="set_shape" getter="get_shape"> + The [Shape2D] that will be used for collision/intersection queries. This stores the actual reference which avoids the shape to be released while being used for queries, so always prefer using this over [member shape_rid]. + </member> <member name="shape_rid" type="RID" setter="set_shape_rid" getter="get_shape_rid"> - The queried shape's [RID]. See also [method set_shape]. + The queried shape's [RID] that will be used for collision/intersection queries. Use this over [member shape] if you want to optimize for performance using the Servers API: + [codeblock] + var shape_rid = PhysicsServer2D.circle_shape_create() + var radius = 64 + PhysicsServer2D.shape_set_data(shape_rid, radius) + + var params = PhysicsShapeQueryParameters2D.new() + params.shape_rid = shape_rid + + # Execute physics queries here... + + # Release the shape when done with physics queries. + PhysicsServer2D.free_rid(shape_rid) + [/codeblock] </member> <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform" default="Transform2D( 1, 0, 0, 1, 0, 0 )"> The queried shape's transform matrix. diff --git a/doc/classes/PhysicsShapeQueryParameters3D.xml b/doc/classes/PhysicsShapeQueryParameters3D.xml index 6606cfbc59..f4191d4862 100644 --- a/doc/classes/PhysicsShapeQueryParameters3D.xml +++ b/doc/classes/PhysicsShapeQueryParameters3D.xml @@ -9,15 +9,6 @@ <tutorials> </tutorials> <methods> - <method name="set_shape"> - <return type="void"> - </return> - <argument index="0" name="shape" type="Resource"> - </argument> - <description> - Sets the [Shape3D] that will be used for collision/intersection queries. - </description> - </method> </methods> <members> <member name="collide_with_areas" type="bool" setter="set_collide_with_areas" getter="is_collide_with_areas_enabled" default="false"> @@ -35,8 +26,24 @@ <member name="margin" type="float" setter="set_margin" getter="get_margin" default="0.0"> The collision margin for the shape. </member> + <member name="shape" type="Resource" setter="set_shape" getter="get_shape"> + The [Shape3D] that will be used for collision/intersection queries. This stores the actual reference which avoids the shape to be released while being used for queries, so always prefer using this over [member shape_rid]. + </member> <member name="shape_rid" type="RID" setter="set_shape_rid" getter="get_shape_rid"> - The queried shape's [RID]. See also [method set_shape]. + The queried shape's [RID] that will be used for collision/intersection queries. Use this over [member shape] if you want to optimize for performance using the Servers API: + [codeblock] + var shape_rid = PhysicsServer3D.shape_create(PhysicsServer3D.SHAPE_SPHERE) + var radius = 2.0 + PhysicsServer3D.shape_set_data(shape_rid, radius) + + var params = PhysicsShapeQueryParameters3D.new() + params.shape_rid = shape_rid + + # Execute physics queries here... + + # Release the shape when done with physics queries. + PhysicsServer3D.free_rid(shape_rid) + [/codeblock] </member> <member name="transform" type="Transform" setter="set_transform" getter="get_transform" default="Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )"> The queried shape's transform matrix. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 7191492098..6a7a6b84f6 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -256,6 +256,9 @@ <member name="audio/output_latency" type="int" setter="" getter="" default="15"> Output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware. </member> + <member name="audio/output_latency.web" type="int" setter="" getter="" default="50"> + Safer override for [member audio/output_latency] in the Web platform, to avoid audio issues especially on mobile devices. + </member> <member name="audio/video_delay_compensation_ms" type="int" setter="" getter="" default="0"> Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing. </member> @@ -1078,13 +1081,13 @@ </member> <member name="rendering/quality/screen_filters/screen_space_aa" type="int" setter="" getter="" default="0"> Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. - Another way to combat specular aliasing is to enable [member rendering/quality/screen_filters/screen_space_roughness_limiter]. + Another way to combat specular aliasing is to enable [member rendering/quality/screen_filters/screen_space_roughness_limiter_enabled]. + </member> + <member name="rendering/quality/screen_filters/screen_space_roughness_limiter_amount" type="float" setter="" getter="" default="0.25"> </member> - <member name="rendering/quality/screen_filters/screen_space_roughness_limiter" type="int" setter="" getter="" default="0"> - Enables the screen-space roughness limiter which increases material roughness in areas with a high normal frequency (i.e. when normals change a lot from pixel to pixel). This helps to reduce the amount of specular aliasing in a scene. Specular aliasing looks like random bright pixels that occur in reflections. + <member name="rendering/quality/screen_filters/screen_space_roughness_limiter_enabled" type="bool" setter="" getter="" default="true"> </member> - <member name="rendering/quality/screen_filters/screen_space_roughness_limiter_curve" type="float" setter="" getter="" default="1.0"> - Curves the amount of the roughness limited effect. A higher value limits the effect to very sharply curved surfaces, while a lower threshold extends the effect to smoother surfaces. + <member name="rendering/quality/screen_filters/screen_space_roughness_limiter_limit" type="float" setter="" getter="" default="0.18"> </member> <member name="rendering/quality/screen_space_reflection/roughness_quality" type="int" setter="" getter="" default="1"> Sets the quality for rough screen-space reflections. Turning off will make all screen space reflections sharp, while higher values make rough reflections look better. @@ -1152,6 +1155,10 @@ <member name="rendering/quality/texture_filters/use_nearest_mipmap_filter" type="bool" setter="" getter="" default="false"> If [code]true[/code], uses nearest-neighbor mipmap filtering when using mipmaps (also called "bilinear filtering"), which will result in visible seams appearing between mipmap stages. This may increase performance in mobile as less memory bandwidth is used. If [code]false[/code], linear mipmap filtering (also called "trilinear filtering") is used. </member> + <member name="rendering/sdfgi/frames_to_converge" type="int" setter="" getter="" default="1"> + </member> + <member name="rendering/sdfgi/probe_ray_count" type="int" setter="" getter="" default="2"> + </member> <member name="rendering/threads/thread_model" type="int" setter="" getter="" default="1"> Thread model for rendering. Rendering on a thread can vastly improve performance, but synchronizing to the main thread can cause a bit more jitter. </member> diff --git a/doc/classes/RayCast2D.xml b/doc/classes/RayCast2D.xml index 51f3f0334d..4a594d3e1a 100644 --- a/doc/classes/RayCast2D.xml +++ b/doc/classes/RayCast2D.xml @@ -135,7 +135,7 @@ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. </member> - <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="false"> + <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> If [code]true[/code], collisions will be reported. </member> <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> diff --git a/doc/classes/RayCast3D.xml b/doc/classes/RayCast3D.xml index 08c6d6f40c..3512da9d77 100644 --- a/doc/classes/RayCast3D.xml +++ b/doc/classes/RayCast3D.xml @@ -138,7 +138,7 @@ <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> The ray's collision mask. Only objects in at least one collision layer enabled in the mask will be detected. </member> - <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="false"> + <member name="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true"> If [code]true[/code], collisions will be reported. </member> <member name="exclude_parent" type="bool" setter="set_exclude_parent_body" getter="get_exclude_parent_body" default="true"> diff --git a/doc/classes/ReflectionProbe.xml b/doc/classes/ReflectionProbe.xml index 84f87c3e71..07d7b646a1 100644 --- a/doc/classes/ReflectionProbe.xml +++ b/doc/classes/ReflectionProbe.xml @@ -13,6 +13,12 @@ <methods> </methods> <members> + <member name="ambient_color" type="Color" setter="set_ambient_color" getter="get_ambient_color" default="Color( 0, 0, 0, 1 )"> + </member> + <member name="ambient_color_energy" type="float" setter="set_ambient_color_energy" getter="get_ambient_color_energy" default="1.0"> + </member> + <member name="ambient_mode" type="int" setter="set_ambient_mode" getter="get_ambient_mode" enum="ReflectionProbe.AmbientMode" default="1"> + </member> <member name="box_projection" type="bool" setter="set_enable_box_projection" getter="is_box_projection_enabled" default="false"> If [code]true[/code], enables box projection. This makes reflections look more correct in rectangle-shaped rooms by offsetting the reflection center depending on the camera's location. </member> @@ -28,17 +34,8 @@ <member name="intensity" type="float" setter="set_intensity" getter="get_intensity" default="1.0"> Defines the reflection intensity. Intensity modulates the strength of the reflection. </member> - <member name="interior_ambient_color" type="Color" setter="set_interior_ambient" getter="get_interior_ambient" default="Color( 0, 0, 0, 1 )"> - Sets the ambient light color to be used when this probe is set to [member interior_enable]. - </member> - <member name="interior_ambient_contrib" type="float" setter="set_interior_ambient_probe_contribution" getter="get_interior_ambient_probe_contribution" default="0.0"> - Sets the contribution value for how much the reflection affects the ambient light for this reflection probe when set to [member interior_enable]. Useful so that ambient light matches the color of the room. - </member> - <member name="interior_ambient_energy" type="float" setter="set_interior_ambient_energy" getter="get_interior_ambient_energy" default="1.0"> - Sets the energy multiplier for this reflection probe's ambient light contribution when set to [member interior_enable]. - </member> - <member name="interior_enable" type="bool" setter="set_as_interior" getter="is_set_as_interior" default="false"> - If [code]true[/code], reflections will ignore sky contribution. Ambient lighting is then controlled by the [code]interior_ambient_*[/code] properties. + <member name="interior" type="bool" setter="set_as_interior" getter="is_set_as_interior" default="false"> + If [code]true[/code], reflections will ignore sky contribution. </member> <member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance" default="0.0"> Sets the max distance away from the probe an object can be before it is culled. @@ -57,5 +54,11 @@ <constant name="UPDATE_ALWAYS" value="1" enum="UpdateMode"> Update the probe every frame. This is needed when you want to capture dynamic objects. However, it results in an increased render time. Use [constant UPDATE_ONCE] whenever possible. </constant> + <constant name="AMBIENT_DISABLED" value="0" enum="AmbientMode"> + </constant> + <constant name="AMBIENT_ENVIRONMENT" value="1" enum="AmbientMode"> + </constant> + <constant name="AMBIENT_COLOR" value="2" enum="AmbientMode"> + </constant> </constants> </class> diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 8a44d213e8..7e5df9c40d 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -152,6 +152,8 @@ </argument> <argument index="8" name="region" type="Rect2" default="Rect2i( 0, 0, 0, 0 )"> </argument> + <argument index="9" name="storage_textures" type="Array" default="[ ]"> + </argument> <description> </description> </method> @@ -188,6 +190,8 @@ </argument> <argument index="9" name="region" type="Rect2" default="Rect2i( 0, 0, 0, 0 )"> </argument> + <argument index="10" name="storage_textures" type="RID[]" default="[ ]"> + </argument> <description> </description> </method> @@ -293,6 +297,16 @@ <description> </description> </method> + <method name="framebuffer_create_empty"> + <return type="RID"> + </return> + <argument index="0" name="size" type="Vector2i"> + </argument> + <argument index="1" name="validate_with_format" type="int" default="-1"> + </argument> + <description> + </description> + </method> <method name="framebuffer_format_create"> <return type="int"> </return> @@ -301,6 +315,14 @@ <description> </description> </method> + <method name="framebuffer_format_create_empty"> + <return type="int"> + </return> + <argument index="0" name="size" type="Vector2i"> + </argument> + <description> + </description> + </method> <method name="framebuffer_format_get_texture_samples"> <return type="int" enum="RenderingDevice.TextureSamples"> </return> @@ -496,6 +518,8 @@ </argument> <argument index="1" name="data" type="PackedByteArray" default="PackedByteArray( )"> </argument> + <argument index="2" name="usage" type="int" default="0"> + </argument> <description> </description> </method> @@ -1285,6 +1309,8 @@ </constant> <constant name="INDEX_BUFFER_FORMAT_UINT32" value="1" enum="IndexBufferFormat"> </constant> + <constant name="STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT" value="1" enum="StorageBufferUsage"> + </constant> <constant name="UNIFORM_TYPE_SAMPLER" value="0" enum="UniformType"> </constant> <constant name="UNIFORM_TYPE_SAMPLER_WITH_TEXTURE" value="1" enum="UniformType"> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index 8832c0ec4d..7539f8ff43 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -1470,6 +1470,16 @@ Sets whether to use a dual paraboloid or a cubemap for the shadow map. Dual paraboloid is faster but may suffer from artifacts. Equivalent to [member OmniLight3D.omni_shadow_mode]. </description> </method> + <method name="light_set_bake_mode"> + <return type="void"> + </return> + <argument index="0" name="light" type="RID"> + </argument> + <argument index="1" name="bake_mode" type="int" enum="RenderingServer.LightBakeMode"> + </argument> + <description> + </description> + </method> <method name="light_set_color"> <return type="void"> </return> @@ -1560,17 +1570,6 @@ Sets the color of the shadow cast by the light. Equivalent to [member Light3D.shadow_color]. </description> </method> - <method name="light_set_use_gi"> - <return type="void"> - </return> - <argument index="0" name="light" type="RID"> - </argument> - <argument index="1" name="enabled" type="bool"> - </argument> - <description> - Sets whether GI probes capture light information from this light. - </description> - </method> <method name="make_sphere_mesh"> <return type="RID"> </return> @@ -2292,40 +2291,37 @@ To place in a scene, attach this reflection probe to an instance using [method instance_set_base] using the returned RID. </description> </method> - <method name="reflection_probe_set_as_interior"> + <method name="reflection_probe_set_ambient_color"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="enable" type="bool"> + <argument index="1" name="color" type="Color"> </argument> <description> - If [code]true[/code], reflections will ignore sky contribution. Equivalent to [member ReflectionProbe.interior_enable]. </description> </method> - <method name="reflection_probe_set_cull_mask"> + <method name="reflection_probe_set_ambient_energy"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="layers" type="int"> + <argument index="1" name="energy" type="float"> </argument> <description> - Sets the render cull mask for this reflection probe. Only instances with a matching cull mask will be rendered by this probe. Equivalent to [member ReflectionProbe.cull_mask]. </description> </method> - <method name="reflection_probe_set_enable_box_projection"> + <method name="reflection_probe_set_ambient_mode"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="enable" type="bool"> + <argument index="1" name="mode" type="int" enum="RenderingServer.ReflectionProbeAmbientMode"> </argument> <description> - If [code]true[/code], uses box projection. This can make reflections look more correct in certain situations. Equivalent to [member ReflectionProbe.box_projection]. </description> </method> - <method name="reflection_probe_set_enable_shadows"> + <method name="reflection_probe_set_as_interior"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> @@ -2333,62 +2329,62 @@ <argument index="1" name="enable" type="bool"> </argument> <description> - If [code]true[/code], computes shadows in the reflection probe. This makes the reflection much slower to compute. Equivalent to [member ReflectionProbe.enable_shadows]. + If [code]true[/code], reflections will ignore sky contribution. Equivalent to [member ReflectionProbe.interior]. </description> </method> - <method name="reflection_probe_set_extents"> + <method name="reflection_probe_set_cull_mask"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="extents" type="Vector3"> + <argument index="1" name="layers" type="int"> </argument> <description> - Sets the size of the area that the reflection probe will capture. Equivalent to [member ReflectionProbe.extents]. + Sets the render cull mask for this reflection probe. Only instances with a matching cull mask will be rendered by this probe. Equivalent to [member ReflectionProbe.cull_mask]. </description> </method> - <method name="reflection_probe_set_intensity"> + <method name="reflection_probe_set_enable_box_projection"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="intensity" type="float"> + <argument index="1" name="enable" type="bool"> </argument> <description> - Sets the intensity of the reflection probe. Intensity modulates the strength of the reflection. Equivalent to [member ReflectionProbe.intensity]. + If [code]true[/code], uses box projection. This can make reflections look more correct in certain situations. Equivalent to [member ReflectionProbe.box_projection]. </description> </method> - <method name="reflection_probe_set_interior_ambient"> + <method name="reflection_probe_set_enable_shadows"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="color" type="Color"> + <argument index="1" name="enable" type="bool"> </argument> <description> - Sets the ambient light color for this reflection probe when set to interior mode. Equivalent to [member ReflectionProbe.interior_ambient_color]. + If [code]true[/code], computes shadows in the reflection probe. This makes the reflection much slower to compute. Equivalent to [member ReflectionProbe.enable_shadows]. </description> </method> - <method name="reflection_probe_set_interior_ambient_energy"> + <method name="reflection_probe_set_extents"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="energy" type="float"> + <argument index="1" name="extents" type="Vector3"> </argument> <description> - Sets the energy multiplier for this reflection probes ambient light contribution when set to interior mode. Equivalent to [member ReflectionProbe.interior_ambient_energy]. + Sets the size of the area that the reflection probe will capture. Equivalent to [member ReflectionProbe.extents]. </description> </method> - <method name="reflection_probe_set_interior_ambient_probe_contribution"> + <method name="reflection_probe_set_intensity"> <return type="void"> </return> <argument index="0" name="probe" type="RID"> </argument> - <argument index="1" name="contrib" type="float"> + <argument index="1" name="intensity" type="float"> </argument> <description> - Sets the contribution value for how much the reflection affects the ambient light for this reflection probe when set to interior mode. Useful so that ambient light matches the color of the room. Equivalent to [member ReflectionProbe.interior_ambient_contrib]. + Sets the intensity of the reflection probe. Intensity modulates the strength of the reflection. Equivalent to [member ReflectionProbe.intensity]. </description> </method> <method name="reflection_probe_set_max_distance"> @@ -3261,6 +3257,12 @@ <constant name="LIGHT_PARAM_MAX" value="18" enum="LightParam"> Represents the size of the [enum LightParam] enum. </constant> + <constant name="LIGHT_BAKE_DISABLED" value="0" enum="LightBakeMode"> + </constant> + <constant name="LIGHT_BAKE_DYNAMIC" value="1" enum="LightBakeMode"> + </constant> + <constant name="LIGHT_BAKE_STATIC" value="2" enum="LightBakeMode"> + </constant> <constant name="LIGHT_OMNI_SHADOW_DUAL_PARABOLOID" value="0" enum="LightOmniShadowMode"> Use a dual paraboloid shadow map for omni lights. </constant> @@ -3288,6 +3290,12 @@ <constant name="REFLECTION_PROBE_UPDATE_ALWAYS" value="1" enum="ReflectionProbeUpdateMode"> Reflection probe will update each frame. This mode is necessary to capture moving objects. </constant> + <constant name="REFLECTION_PROBE_AMBIENT_DISABLED" value="0" enum="ReflectionProbeAmbientMode"> + </constant> + <constant name="REFLECTION_PROBE_AMBIENT_ENVIRONMENT" value="1" enum="ReflectionProbeAmbientMode"> + </constant> + <constant name="REFLECTION_PROBE_AMBIENT_COLOR" value="2" enum="ReflectionProbeAmbientMode"> + </constant> <constant name="DECAL_TEXTURE_ALBEDO" value="0" enum="DecalTexture"> </constant> <constant name="DECAL_TEXTURE_NORMAL" value="1" enum="DecalTexture"> @@ -3412,13 +3420,16 @@ <constant name="VIEWPORT_DEBUG_DRAW_SSAO" value="12" enum="ViewportDebugDraw"> Draws the screen space ambient occlusion texture instead of the scene so that you can clearly see how it is affecting objects. In order for this display mode to work, you must have [member Environment.ssao_enabled] set in your [WorldEnvironment]. </constant> - <constant name="VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER" value="13" enum="ViewportDebugDraw"> - Draws the roughness limiter post process over the Viewport so you can see where it has an effect. It must be enabled in [member ProjectSettings.rendering/quality/screen_filters/screen_space_roughness_limiter] to work. - </constant> - <constant name="VIEWPORT_DEBUG_DRAW_PSSM_SPLITS" value="14" enum="ViewportDebugDraw"> + <constant name="VIEWPORT_DEBUG_DRAW_PSSM_SPLITS" value="13" enum="ViewportDebugDraw"> Colors each PSSM split for the [DirectionalLight3D]s in the scene a different color so you can see where the splits are. In order they will be colored red, green, blue, yellow. </constant> - <constant name="VIEWPORT_DEBUG_DRAW_DECAL_ATLAS" value="15" enum="ViewportDebugDraw"> + <constant name="VIEWPORT_DEBUG_DRAW_DECAL_ATLAS" value="14" enum="ViewportDebugDraw"> + </constant> + <constant name="VIEWPORT_DEBUG_DRAW_SDFGI" value="15" enum="ViewportDebugDraw"> + </constant> + <constant name="VIEWPORT_DEBUG_DRAW_SDFGI_PROBES" value="16" enum="ViewportDebugDraw"> + </constant> + <constant name="VIEWPORT_DEBUG_DRAW_GI_BUFFER" value="17" enum="ViewportDebugDraw"> </constant> <constant name="SKY_MODE_QUALITY" value="0" enum="SkyMode"> Uses high quality importance sampling to process the radiance map. In general, this results in much higher quality than [constant Sky.PROCESS_MODE_REALTIME] but takes much longer to generate. This should not be used if you plan on changing the sky at runtime. If you are finding that the reflection is not blurry enough and is showing sparkles or fireflies, try increasing [member ProjectSettings.rendering/quality/reflections/ggx_samples]. diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml index a3fd2e81fd..d56dc1e17c 100644 --- a/doc/classes/RigidBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -34,9 +34,9 @@ <method name="add_force"> <return type="void"> </return> - <argument index="0" name="offset" type="Vector2"> + <argument index="0" name="force" type="Vector2"> </argument> - <argument index="1" name="force" type="Vector2"> + <argument index="1" name="position" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> Adds a positioned force to the body. Both the force and the offset from the body origin are in global coordinates. @@ -54,7 +54,7 @@ <method name="apply_central_impulse"> <return type="void"> </return> - <argument index="0" name="impulse" type="Vector2"> + <argument index="0" name="impulse" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> Applies a directional impulse without affecting rotation. @@ -63,9 +63,9 @@ <method name="apply_impulse"> <return type="void"> </return> - <argument index="0" name="offset" type="Vector2"> + <argument index="0" name="impulse" type="Vector2"> </argument> - <argument index="1" name="impulse" type="Vector2"> + <argument index="1" name="position" type="Vector2" default="Vector2( 0, 0 )"> </argument> <description> Applies a positioned impulse to the body. An impulse is time-independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason it should only be used when simulating one-time impacts (use the "_force" functions otherwise). The position uses the rotation of the global coordinate system, but is centered at the object's origin. diff --git a/doc/classes/RigidBody3D.xml b/doc/classes/RigidBody3D.xml index 063cc3ca59..efd55f5566 100644 --- a/doc/classes/RigidBody3D.xml +++ b/doc/classes/RigidBody3D.xml @@ -37,7 +37,7 @@ </return> <argument index="0" name="force" type="Vector3"> </argument> - <argument index="1" name="position" type="Vector3"> + <argument index="1" name="position" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> Adds a constant directional force (i.e. acceleration). @@ -66,9 +66,9 @@ <method name="apply_impulse"> <return type="void"> </return> - <argument index="0" name="position" type="Vector3"> + <argument index="0" name="impulse" type="Vector3"> </argument> - <argument index="1" name="impulse" type="Vector3"> + <argument index="1" name="position" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> <description> Applies a positioned impulse to the body. An impulse is time independent! Applying an impulse every frame would result in a framerate-dependent force. For this reason it should only be used when simulating one-time impacts. The position uses the rotation of the global coordinate system, but is centered at the object's origin. diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 6d9def7ccb..b692051097 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -412,7 +412,8 @@ <argument index="1" name="from" type="int" default="0"> </argument> <description> - Finds the first occurrence of a substring. Returns the starting position of the substring or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + Returns the index of the [b]first[/b] case-sensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the end of the string. + [b]Note:[/b] If you just want to know whether a string contains a substring, use the [code]in[/code] operator as follows: [codeblock] # Will evaluate to `false`. @@ -421,15 +422,6 @@ [/codeblock] </description> </method> - <method name="find_last"> - <return type="int"> - </return> - <argument index="0" name="what" type="String"> - </argument> - <description> - Finds the last occurrence of a substring. Returns the starting position of the substring or [code]-1[/code] if not found. - </description> - </method> <method name="findn"> <return type="int"> </return> @@ -438,7 +430,7 @@ <argument index="1" name="from" type="int" default="0"> </argument> <description> - Finds the first occurrence of a substring, ignoring case. Returns the starting position of the substring or [code]-1[/code] if not found. Optionally, the initial search index can be passed. + Returns the index of the [b]first[/b] case-insensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the end of the string. </description> </method> <method name="format"> @@ -801,7 +793,7 @@ <argument index="1" name="from" type="int" default="-1"> </argument> <description> - Performs a case-sensitive search for a substring, but starts from the end of the string instead of the beginning. + Returns the index of the [b]last[/b] case-sensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the beginning of the string. </description> </method> <method name="rfindn"> @@ -812,7 +804,7 @@ <argument index="1" name="from" type="int" default="-1"> </argument> <description> - Performs a case-insensitive search for a substring, but starts from the end of the string instead of the beginning. + Returns the index of the [b]last[/b] case-insensitive occurrence of the specified string in this instance, or [code]-1[/code]. Optionally, the starting search index can be specified, continuing to the beginning of the string. </description> </method> <method name="right"> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 0c6615c53b..b7b4278da0 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -48,6 +48,7 @@ <return type="void"> </return> <description> + Centers the viewport on the line the editing cursor is at. This also resets the [member scroll_horizontal] value to [code]0[/code]. </description> </method> <method name="clear_colors"> @@ -334,6 +335,7 @@ </argument> <description> Perform selection, from line/column to line/column. + If [member selecting_enabled] is [code]false[/code], no selection will occur. </description> </method> <method name="select_all"> @@ -341,6 +343,7 @@ </return> <description> Select all the text. + If [member selecting_enabled] is [code]false[/code], no selection will occur. </description> </method> <method name="set_line"> @@ -439,8 +442,10 @@ If [code]true[/code], the line containing the cursor is highlighted. </member> <member name="minimap_draw" type="bool" setter="draw_minimap" getter="is_drawing_minimap" default="false"> + If [code]true[/code], a minimap is shown, providing an outline of your source code. </member> <member name="minimap_width" type="int" setter="set_minimap_width" getter="get_minimap_width" default="80"> + The width, in pixels, of the minimap. </member> <member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" override="true" enum="Control.CursorShape" default="1" /> <member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color" default="false"> @@ -456,8 +461,11 @@ The current vertical scroll value. </member> <member name="selecting_enabled" type="bool" setter="set_selecting_enabled" getter="is_selecting_enabled" default="true"> + If [code]true[/code], text can be selected. + If [code]false[/code], text can not be selected by the user or by the [method select] or [method select_all] methods. </member> <member name="shortcut_keys_enabled" type="bool" setter="set_shortcut_keys_enabled" getter="is_shortcut_keys_enabled" default="true"> + If [code]true[/code], shortcut keys for context menu items are enabled, even if the context menu is disabled. </member> <member name="show_line_numbers" type="bool" setter="set_show_line_numbers" getter="is_show_line_numbers_enabled" default="false"> If [code]true[/code], line numbers are displayed to the left of the text. diff --git a/doc/classes/TextureButton.xml b/doc/classes/TextureButton.xml index 0e2872755e..a5172586fe 100644 --- a/doc/classes/TextureButton.xml +++ b/doc/classes/TextureButton.xml @@ -15,6 +15,12 @@ <member name="expand" type="bool" setter="set_expand" getter="get_expand" default="false"> If [code]true[/code], the texture stretches to the edges of the node's bounding rectangle using the [member stretch_mode]. If [code]false[/code], the texture will not scale with the node. </member> + <member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h" default="false"> + If [code]true[/code], texture is flipped horizontally. + </member> + <member name="flip_v" type="bool" setter="set_flip_v" getter="is_flipped_v" default="false"> + If [code]true[/code], texture is flipped vertically. + </member> <member name="stretch_mode" type="int" setter="set_stretch_mode" getter="get_stretch_mode" enum="TextureButton.StretchMode" default="0"> Controls the texture's behavior when you resize the node's bounding rectangle, [b]only if[/b] [member expand] is [code]true[/code]. Set it to one of the [enum StretchMode] constants. See the constants to learn more. </member> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 7f4a212679..32895310d1 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -44,7 +44,7 @@ </return> <description> Returns the vector's angle in radians with respect to the X axis, or [code](1, 0)[/code] vector. - Equivalent to the result of [method @GDScript.atan2] when called with the vector's [member x] and [member y] as parameters: [code]atan2(x, y)[/code]. + Equivalent to the result of [method @GDScript.atan2] when called with the vector's [member y] and [member x] as parameters: [code]atan2(y, x)[/code]. </description> </method> <method name="angle_to"> diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 3b52c80c9a..8a2c6b73d8 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -377,15 +377,18 @@ <constant name="DEBUG_DRAW_SSAO" value="12" enum="DebugDraw"> Draws the screen-space ambient occlusion texture instead of the scene so that you can clearly see how it is affecting objects. In order for this display mode to work, you must have [member Environment.ssao_enabled] set in your [WorldEnvironment]. </constant> - <constant name="DEBUG_DRAW_ROUGHNESS_LIMITER" value="13" enum="DebugDraw"> - Draws the roughness limiter post process over the Viewport so you can see where it has an effect. It must be enabled in [member ProjectSettings.rendering/quality/screen_filters/screen_space_roughness_limiter] to work. - </constant> - <constant name="DEBUG_DRAW_PSSM_SPLITS" value="14" enum="DebugDraw"> + <constant name="DEBUG_DRAW_PSSM_SPLITS" value="13" enum="DebugDraw"> Colors each PSSM split for the [DirectionalLight3D]s in the scene a different color so you can see where the splits are. In order, they will be colored red, green, blue, and yellow. </constant> - <constant name="DEBUG_DRAW_DECAL_ATLAS" value="15" enum="DebugDraw"> + <constant name="DEBUG_DRAW_DECAL_ATLAS" value="14" enum="DebugDraw"> Draws the decal atlas used by [Decal]s and light projector textures in the upper left quadrant of the [Viewport]. </constant> + <constant name="DEBUG_DRAW_SDFGI" value="15" enum="DebugDraw"> + </constant> + <constant name="DEBUG_DRAW_SDFGI_PROBES" value="16" enum="DebugDraw"> + </constant> + <constant name="DEBUG_DRAW_GI_BUFFER" value="17" enum="DebugDraw"> + </constant> <constant name="DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST" value="0" enum="DefaultCanvasItemTextureFilter"> The texture filter reads from the nearest pixel only. The simplest and fastest method of filtering, but the texture will look pixelized. </constant> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index e1a0f1f22a..c1a991fca1 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -377,9 +377,9 @@ </constant> <constant name="CONTENT_SCALE_MODE_DISABLED" value="0" enum="ContentScaleMode"> </constant> - <constant name="CONTENT_SCALE_MODE_OBJECTS" value="1" enum="ContentScaleMode"> + <constant name="CONTENT_SCALE_MODE_CANVAS_ITEMS" value="1" enum="ContentScaleMode"> </constant> - <constant name="CONTENT_SCALE_MODE_PIXELS" value="2" enum="ContentScaleMode"> + <constant name="CONTENT_SCALE_MODE_VIEWPORT" value="2" enum="ContentScaleMode"> </constant> <constant name="CONTENT_SCALE_ASPECT_IGNORE" value="0" enum="ContentScaleAspect"> </constant> diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index 7af7678f63..0d2d6b38a7 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -51,6 +51,14 @@ public: int get_directional_light_shadow_size(RID p_light_intance) { return 0; } void set_directional_shadow_count(int p_count) {} + /* SDFGI UPDATE */ + + virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) {} + virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const { return 0; } + virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const { return AABB(); } + virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const { return 0; } + virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) {} + /* SKY API */ RID sky_create() { return RID(); } @@ -87,6 +95,11 @@ public: virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {} virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) {} + virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {} + + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) {} + virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) {} + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {} void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} @@ -114,6 +127,7 @@ public: RID light_instance_create(RID p_light) { return RID(); } void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) {} + virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {} void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) {} void light_instance_mark_visible(RID p_light_instance) {} @@ -137,9 +151,13 @@ public: virtual bool gi_probe_needs_update(RID p_probe) const { return false; } virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) {} + virtual void gi_probe_set_quality(RS::GIProbeQuality) {} + virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {} void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) {} virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) {} + virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) {} + virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) {} void set_scene_pass(uint64_t p_pass) {} virtual void set_time(double p_time, double p_step) {} @@ -148,7 +166,7 @@ public: virtual RID render_buffers_create() { return RID(); } virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa) {} - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) {} + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) {} virtual bool screen_space_roughness_limiter_is_active() const { return false; } virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {} @@ -158,6 +176,7 @@ public: bool free(RID p_rid) { return true; } virtual void update() {} + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) {} RasterizerSceneDummy() {} ~RasterizerSceneDummy() {} @@ -576,7 +595,8 @@ public: void light_set_negative(RID p_light, bool p_enable) {} void light_set_cull_mask(RID p_light, uint32_t p_mask) {} void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {} - void light_set_use_gi(RID p_light, bool p_enabled) {} + void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {} + void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {} void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {} @@ -595,7 +615,8 @@ public: AABB light_get_aabb(RID p_light) const { return AABB(); } float light_get_param(RID p_light, RS::LightParam p_param) { return 0.0; } Color light_get_color(RID p_light) { return Color(); } - bool light_get_use_gi(RID p_light) { return false; } + virtual RS::LightBakeMode light_get_bake_mode(RID p_light) { return RS::LIGHT_BAKE_DISABLED; } + virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) { return 0; } uint64_t light_get_version(RID p_light) const { return 0; } /* PROBE API */ @@ -604,9 +625,9 @@ public: void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {} void reflection_probe_set_intensity(RID p_probe, float p_intensity) {} - void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {} - void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {} - void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) {} + void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {} + void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) {} + void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) {} void reflection_probe_set_max_distance(RID p_probe, float p_distance) {} void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {} void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {} diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 2e36de5c79..a5e85424b7 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -247,6 +247,9 @@ void ShaderCompilerGLES2::_dump_function_deps(SL::ShaderNode *p_node, const Stri for (int i = 0; i < fnode->arguments.size(); i++) { if (i > 0) header += ", "; + if (fnode->arguments[i].is_const) { + header += "const "; + } if (fnode->arguments[i].type == SL::TYPE_STRUCT) { header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name); } else { diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 15ad187ab4..186804dbb1 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -245,7 +245,7 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St continue; } - if_v6id = (uint32_t)c.index.to_int64(); + if_v6id = (uint32_t)c.index.to_int(); if (type == IP::TYPE_IPV6) { break; // IPv6 uses index. } diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index c9e78678a8..f37e21aa93 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -38,7 +38,7 @@ #include "thirdparty/spirv-reflect/spirv_reflect.h" -//#define FORCE_FULL_BARRIER +#define FORCE_FULL_BARRIER void RenderingDeviceVulkan::_add_dependency(RID p_id, RID p_depends_on) { if (!dependency_map.has(p_depends_on)) { @@ -3203,6 +3203,63 @@ RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_c return id; } +RenderingDevice::FramebufferFormatID RenderingDeviceVulkan::framebuffer_format_create_empty(const Size2i &p_size) { + ERR_FAIL_COND_V(p_size.width <= 0 || p_size.height <= 0, INVALID_FORMAT_ID); + + FramebufferFormatKey key; + key.empty_size = p_size; + + const Map<FramebufferFormatKey, FramebufferFormatID>::Element *E = framebuffer_format_cache.find(key); + if (E) { + //exists, return + return E->get(); + } + + VkSubpassDescription subpass; + subpass.flags = 0; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.inputAttachmentCount = 0; //unsupported for now + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 0; + subpass.pColorAttachments = nullptr; + subpass.pDepthStencilAttachment = nullptr; + subpass.pResolveAttachments = nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkRenderPassCreateInfo render_pass_create_info; + render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_create_info.pNext = nullptr; + render_pass_create_info.flags = 0; + render_pass_create_info.attachmentCount = 0; + render_pass_create_info.pAttachments = nullptr; + render_pass_create_info.subpassCount = 1; + render_pass_create_info.pSubpasses = &subpass; + render_pass_create_info.dependencyCount = 0; + render_pass_create_info.pDependencies = nullptr; + + VkRenderPass render_pass; + VkResult res = vkCreateRenderPass(device, &render_pass_create_info, nullptr, &render_pass); + + ERR_FAIL_COND_V_MSG(res, VK_NULL_HANDLE, "vkCreateRenderPass for empty fb failed with error " + itos(res) + "."); + + if (render_pass == VK_NULL_HANDLE) { //was likely invalid + return INVALID_ID; + } + + FramebufferFormatID id = FramebufferFormatID(framebuffer_format_cache.size()) | (FramebufferFormatID(ID_TYPE_FRAMEBUFFER_FORMAT) << FramebufferFormatID(ID_BASE_SHIFT)); + + E = framebuffer_format_cache.insert(key, id); + + FramebufferFormat fb_format; + fb_format.E = E; + fb_format.color_attachments = 0; + fb_format.render_pass = render_pass; + fb_format.samples = TEXTURE_SAMPLES_1; + framebuffer_formats[id] = fb_format; + return id; +} + RenderingDevice::TextureSamples RenderingDeviceVulkan::framebuffer_format_get_texture_samples(FramebufferFormatID p_format) { Map<FramebufferFormatID, FramebufferFormat>::Element *E = framebuffer_formats.find(p_format); ERR_FAIL_COND_V(!E, TEXTURE_SAMPLES_1); @@ -3214,6 +3271,16 @@ RenderingDevice::TextureSamples RenderingDeviceVulkan::framebuffer_format_get_te /**** RENDER TARGET ****/ /***********************/ +RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check) { + _THREAD_SAFE_METHOD_ + Framebuffer framebuffer; + framebuffer.format_id = framebuffer_format_create_empty(p_size); + ERR_FAIL_COND_V(p_format_check != INVALID_FORMAT_ID && framebuffer.format_id != p_format_check, RID()); + framebuffer.size = p_size; + + return framebuffer_owner.make_rid(framebuffer); +} + RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check) { _THREAD_SAFE_METHOD_ @@ -4205,13 +4272,18 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Ve return uniform_buffer_owner.make_rid(buffer); } -RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data) { +RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, uint32_t p_usage) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(p_data.size() && (uint32_t)p_data.size() != p_size_bytes, RID()); Buffer buffer; - Error err = _buffer_allocate(&buffer, p_size_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY); + buffer.usage = p_usage; + uint32_t flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + if (p_usage & STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT) { + flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; + } + Error err = _buffer_allocate(&buffer, p_size_bytes, flags, VMA_MEMORY_USAGE_GPU_ONLY); ERR_FAIL_COND_V(err != OK, RID()); if (p_data.size()) { @@ -4420,7 +4492,7 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms, } } ERR_FAIL_COND_V_MSG(uniform_idx == -1, RID(), - "All the shader bindings for the given set must be covered by the uniforms provided."); + "All the shader bindings for the given set must be covered by the uniforms provided. Binding (" + itos(set_uniform.binding) + ") was not provided."); const Uniform &uniform = uniforms[uniform_idx]; @@ -5475,7 +5547,7 @@ Error RenderingDeviceVulkan::_draw_list_setup_framebuffer(Framebuffer *p_framebu return OK; } -Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents) { +Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures) { VkRenderPassBeginInfo render_pass_begin; render_pass_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; render_pass_begin.pNext = nullptr; @@ -5520,6 +5592,37 @@ Error RenderingDeviceVulkan::_draw_list_render_pass_begin(Framebuffer *framebuff render_pass_begin.clearValueCount = clear_values.size(); render_pass_begin.pClearValues = clear_values.ptr(); + for (int i = 0; i < p_storage_textures.size(); i++) { + Texture *texture = texture_owner.getornull(p_storage_textures[i]); + ERR_CONTINUE_MSG(!(texture->usage_flags & TEXTURE_USAGE_STORAGE_BIT), "Supplied storage texture " + itos(i) + " for draw list ist not set to be used for storage."); + + if (texture->usage_flags & TEXTURE_USAGE_SAMPLING_BIT) { + //must change layout to general + VkImageMemoryBarrier image_memory_barrier; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + image_memory_barrier.oldLayout = texture->layout; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL; + + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = texture->image; + image_memory_barrier.subresourceRange.aspectMask = texture->read_aspect_mask; + image_memory_barrier.subresourceRange.baseMipLevel = texture->base_mipmap; + image_memory_barrier.subresourceRange.levelCount = texture->mipmaps; + image_memory_barrier.subresourceRange.baseArrayLayer = texture->base_layer; + image_memory_barrier.subresourceRange.layerCount = texture->layers; + + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); + + texture->layout = VK_IMAGE_LAYOUT_GENERAL; + + draw_list_storage_textures.push_back(p_storage_textures[i]); + } + } + vkCmdBeginRenderPass(command_buffer, &render_pass_begin, subpass_contents); //mark textures as bound @@ -5576,7 +5679,7 @@ void RenderingDeviceVulkan::_draw_list_insert_clear_region(DrawList *draw_list, vkCmdClearAttachments(draw_list->command_buffer, clear_attachments.size(), clear_attachments.ptr(), 1, &cr); } -RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { +RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V_MSG(draw_list != nullptr, INVALID_ID, "Only one draw list can be active at the same time."); @@ -5626,7 +5729,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu ERR_FAIL_COND_V(err != OK, INVALID_ID); VkCommandBuffer command_buffer = frames[frame].draw_command_buffer; - err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE); + err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, command_buffer, VK_SUBPASS_CONTENTS_INLINE, p_storage_textures); if (err != OK) { return INVALID_ID; @@ -5666,7 +5769,7 @@ RenderingDevice::DrawListID RenderingDeviceVulkan::draw_list_begin(RID p_framebu return ID_TYPE_DRAW_LIST; } -Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { +Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND_V(p_splits < 1, ERR_INVALID_DECLARATION); @@ -5748,7 +5851,7 @@ Error RenderingDeviceVulkan::draw_list_begin_split(RID p_framebuffer, uint32_t p ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE); VkCommandBuffer frame_command_buffer = frames[frame].draw_command_buffer; - err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + err = _draw_list_render_pass_begin(framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, viewport_offset, viewport_size, vkframebuffer, render_pass, frame_command_buffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, p_storage_textures); if (err != OK) { return ERR_CANT_CREATE; @@ -6229,6 +6332,33 @@ void RenderingDeviceVulkan::draw_list_end() { draw_list_bound_textures.clear(); + for (int i = 0; i < draw_list_storage_textures.size(); i++) { + Texture *texture = texture_owner.getornull(draw_list_storage_textures[i]); + + VkImageMemoryBarrier image_memory_barrier; + image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + image_memory_barrier.pNext = nullptr; + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.oldLayout = texture->layout; + image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + image_memory_barrier.image = texture->image; + image_memory_barrier.subresourceRange.aspectMask = texture->read_aspect_mask; + image_memory_barrier.subresourceRange.baseMipLevel = texture->base_mipmap; + image_memory_barrier.subresourceRange.levelCount = texture->mipmaps; + image_memory_barrier.subresourceRange.baseArrayLayer = texture->base_layer; + image_memory_barrier.subresourceRange.layerCount = texture->layers; + + vkCmdPipelineBarrier(frames[frame].draw_command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); + + texture->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + + draw_list_storage_textures.clear(); + // To ensure proper synchronization, we must make sure rendering is done before: // * Some buffer is copied // * Another render pass happens (since we may be done @@ -6495,6 +6625,62 @@ void RenderingDeviceVulkan::compute_list_dispatch(ComputeListID p_list, uint32_t vkCmdDispatch(cl->command_buffer, p_x_groups, p_y_groups, p_z_groups); } +void RenderingDeviceVulkan::compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) { + ERR_FAIL_COND(p_list != ID_TYPE_COMPUTE_LIST); + ERR_FAIL_COND(!compute_list); + + ComputeList *cl = compute_list; + Buffer *buffer = storage_buffer_owner.getornull(p_buffer); + ERR_FAIL_COND(!buffer); + + ERR_FAIL_COND_MSG(!(buffer->usage & STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT), "Buffer provided was not created to do indirect dispatch."); + + ERR_FAIL_COND_MSG(p_offset + 12 > buffer->size, "Offset provided (+12) is past the end of buffer."); + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!cl->validation.active, "Submitted Compute Lists can no longer be modified."); +#endif + +#ifdef DEBUG_ENABLED + + ERR_FAIL_COND_MSG(!cl->validation.pipeline_active, "No compute pipeline was set before attempting to draw."); + + if (cl->validation.pipeline_push_constant_size > 0) { + //using push constants, check that they were supplied + ERR_FAIL_COND_MSG(!cl->validation.pipeline_push_constant_supplied, + "The shader in this pipeline requires a push constant to be set before drawing, but it's not present."); + } + +#endif + + //Bind descriptor sets + + for (uint32_t i = 0; i < cl->state.set_count; i++) { + if (cl->state.sets[i].pipeline_expected_format == 0) { + continue; //nothing expected by this pipeline + } +#ifdef DEBUG_ENABLED + if (cl->state.sets[i].pipeline_expected_format != cl->state.sets[i].uniform_set_format) { + if (cl->state.sets[i].uniform_set_format == 0) { + ERR_FAIL_MSG("Uniforms were never supplied for set (" + itos(i) + ") at the time of drawing, which are required by the pipeline"); + } else if (uniform_set_owner.owns(cl->state.sets[i].uniform_set)) { + UniformSet *us = uniform_set_owner.getornull(cl->state.sets[i].uniform_set); + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + "):\n" + _shader_uniform_debug(us->shader_id, us->shader_set) + "\nare not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); + } else { + ERR_FAIL_MSG("Uniforms supplied for set (" + itos(i) + ", which was was just freed) are not the same format as required by the pipeline shader. Pipeline shader requires the following bindings:\n" + _shader_uniform_debug(cl->state.pipeline_shader)); + } + } +#endif + if (!cl->state.sets[i].bound) { + //All good, see if this requires re-binding + vkCmdBindDescriptorSets(cl->command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, cl->state.pipeline_layout, i, 1, &cl->state.sets[i].descriptor_set, 0, nullptr); + cl->state.sets[i].bound = true; + } + } + + vkCmdDispatchIndirect(cl->command_buffer, buffer->buffer, p_offset); +} + void RenderingDeviceVulkan::compute_list_add_barrier(ComputeListID p_list) { #ifdef FORCE_FULL_BARRIER _full_barrier(true); @@ -6534,10 +6720,17 @@ void RenderingDeviceVulkan::compute_list_end() { #ifdef FORCE_FULL_BARRIER _full_barrier(true); #else - _memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT, true); + _memory_barrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INDIRECT_COMMAND_READ_BIT, true); #endif } +void RenderingDeviceVulkan::full_barrier() { +#ifndef DEBUG_ENABLED + ERR_PRINT("Full barrier is debug-only, should not be used in production"); +#endif + _full_barrier(true); +} + #if 0 void RenderingDeviceVulkan::draw_list_render_secondary_to_framebuffer(ID p_framebuffer, ID *p_draw_lists, uint32_t p_draw_list_count, InitialAction p_initial_action, FinalAction p_final_action, const Vector<Variant> &p_clear_colors) { diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index eac3250bf7..936448dbbd 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -204,10 +204,17 @@ class RenderingDeviceVulkan : public RenderingDevice { Error _insert_staging_block(); struct Buffer { - uint32_t size = 0; - VkBuffer buffer = VK_NULL_HANDLE; - VmaAllocation allocation = nullptr; + uint32_t size; + uint32_t usage; + VkBuffer buffer; + VmaAllocation allocation; VkDescriptorBufferInfo buffer_info; //used for binding + Buffer() { + size = 0; + usage = 0; + buffer = VK_NULL_HANDLE; + allocation = nullptr; + } }; Error _buffer_allocate(Buffer *p_buffer, uint32_t p_size, uint32_t p_usage, VmaMemoryUsage p_mapping); @@ -229,8 +236,13 @@ class RenderingDeviceVulkan : public RenderingDevice { // used for the render pipelines. struct FramebufferFormatKey { + Size2i empty_size; Vector<AttachmentFormat> attachments; bool operator<(const FramebufferFormatKey &p_key) const { + if (empty_size != p_key.empty_size) { + return empty_size < p_key.empty_size; + } + int as = attachments.size(); int bs = p_key.attachments.size(); if (as != bs) { @@ -773,12 +785,13 @@ class RenderingDeviceVulkan : public RenderingDevice { uint32_t draw_list_count; bool draw_list_split; Vector<RID> draw_list_bound_textures; + Vector<RID> draw_list_storage_textures; bool draw_list_unbind_color_textures; bool draw_list_unbind_depth_textures; void _draw_list_insert_clear_region(DrawList *draw_list, Framebuffer *framebuffer, Point2i viewport_offset, Point2i viewport_size, bool p_clear_color, const Vector<Color> &p_clear_colors, bool p_clear_depth, float p_depth, uint32_t p_stencil); Error _draw_list_setup_framebuffer(Framebuffer *p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, VkFramebuffer *r_framebuffer, VkRenderPass *r_render_pass); - Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents); + Error _draw_list_render_pass_begin(Framebuffer *framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_colors, float p_clear_depth, uint32_t p_clear_stencil, Point2i viewport_offset, Point2i viewport_size, VkFramebuffer vkframebuffer, VkRenderPass render_pass, VkCommandBuffer command_buffer, VkSubpassContents subpass_contents, const Vector<RID> &p_storage_textures); _FORCE_INLINE_ DrawList *_get_draw_list_ptr(DrawListID p_id); /**********************/ @@ -923,9 +936,11 @@ public: /*********************/ virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format); + virtual FramebufferFormatID framebuffer_format_create_empty(const Size2i &p_size); virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format); virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID); + virtual RID framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check = INVALID_ID); virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer); @@ -961,7 +976,7 @@ public: /*****************/ virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>()); - virtual RID storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>()); + virtual RID storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>(), uint32_t p_usage = 0); virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>()); virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set); @@ -998,8 +1013,8 @@ public: virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()); - virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); - virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); + virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); + virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline); virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index); @@ -1026,8 +1041,11 @@ public: virtual void compute_list_add_barrier(ComputeListID p_list); virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups); + virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset); virtual void compute_list_end(); + virtual void full_barrier(); + /**************/ /**** FREE ****/ /**************/ diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index f880ece88b..17b03fd479 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -31,6 +31,7 @@ #include "animation_bezier_editor.h" #include "editor/editor_node.h" +#include "editor_scale.h" float AnimationBezierTrackEdit::_bezier_h_to_pixel(float p_h) { float h = p_h; @@ -539,7 +540,7 @@ void AnimationBezierTrackEdit::_play_position_draw() { if (px >= timeline->get_name_limit() && px < (get_size().width - timeline->get_buttons_width())) { Color color = get_theme_color("accent_color", "Editor"); - play_position->draw_line(Point2(px, 0), Point2(px, h), color); + play_position->draw_line(Point2(px, 0), Point2(px, h), color, Math::round(2 * EDSCALE)); } } @@ -558,6 +559,7 @@ void AnimationBezierTrackEdit::set_root(Node *p_root) { void AnimationBezierTrackEdit::_zoom_changed() { update(); + play_position->update(); } String AnimationBezierTrackEdit::get_tooltip(const Point2 &p_pos) const { diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index f36e84dab6..1d6770a32e 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -3557,7 +3557,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p if (track_path == np) { value = p_value; //all good } else { - int sep = track_path.find_last(":"); + int sep = track_path.rfind(":"); if (sep != -1) { String base_path = track_path.substr(0, sep); if (base_path == np) { @@ -3656,7 +3656,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari value = p_value; //all good } else { String tpath = animation->track_get_path(i); - int index = tpath.find_last(":"); + int index = tpath.rfind(":"); if (NodePath(tpath.substr(0, index + 1)) == np) { String subindex = tpath.substr(index + 1, tpath.length() - index); value = p_value.get(subindex); diff --git a/editor/debugger/editor_performance_profiler.cpp b/editor/debugger/editor_performance_profiler.cpp new file mode 100644 index 0000000000..47fe282758 --- /dev/null +++ b/editor/debugger/editor_performance_profiler.cpp @@ -0,0 +1,394 @@ +/*************************************************************************/ +/* editor_performance_profiler.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "editor_performance_profiler.h" + +#include "editor/editor_scale.h" +#include "editor/editor_settings.h" +#include "main/performance.h" + +EditorPerformanceProfiler::Monitor::Monitor() {} + +EditorPerformanceProfiler::Monitor::Monitor(String p_name, String p_base, int p_frame_index, Performance::MonitorType p_type, TreeItem *p_item) { + type = p_type; + item = p_item; + frame_index = p_frame_index; + name = p_name; + base = p_base; +} + +void EditorPerformanceProfiler::Monitor::update_value(float p_value) { + ERR_FAIL_COND(!item); + String label = EditorPerformanceProfiler::_create_label(p_value, type); + String tooltip = label; + switch (type) { + case Performance::MONITOR_TYPE_MEMORY: { + tooltip = label; + } break; + case Performance::MONITOR_TYPE_TIME: { + tooltip = label; + } break; + default: { + tooltip += " " + item->get_text(0); + } break; + } + item->set_text(1, label); + item->set_tooltip(1, tooltip); + + if (p_value > max) { + max = p_value; + } +} + +void EditorPerformanceProfiler::Monitor::reset() { + history.clear(); + max = 0.0f; + if (item) { + item->set_text(1, ""); + item->set_tooltip(1, ""); + } +} + +String EditorPerformanceProfiler::_create_label(float p_value, Performance::MonitorType p_type) { + switch (p_type) { + case Performance::MONITOR_TYPE_MEMORY: { + return String::humanize_size(p_value); + } + case Performance::MONITOR_TYPE_TIME: { + return rtos(p_value * 1000).pad_decimals(2) + " ms"; + } + default: { + return rtos(p_value); + } + } +} + +void EditorPerformanceProfiler::_monitor_select() { + monitor_draw->update(); +} + +void EditorPerformanceProfiler::_monitor_draw() { + Vector<StringName> active; + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (i.value().item->is_checked(0)) { + active.push_back(i.key()); + } + } + + if (active.empty()) { + info_message->show(); + return; + } + + info_message->hide(); + + Ref<StyleBox> graph_style_box = get_theme_stylebox("normal", "TextEdit"); + Ref<Font> graph_font = get_theme_font("font", "TextEdit"); + + int columns = int(Math::ceil(Math::sqrt(float(active.size())))); + int rows = int(Math::ceil(float(active.size()) / float(columns))); + if (active.size() == 1) { + rows = 1; + } + Size2i cell_size = Size2i(monitor_draw->get_size()) / Size2i(columns, rows); + float spacing = float(POINT_SEPARATION) / float(columns); + float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4f : 0.55f; + float hue_shift = 1.0f / float(monitors.size()); + + for (int i = 0; i < active.size(); i++) { + Monitor ¤t = monitors[active[i]]; + Rect2i rect(Point2i(i % columns, i / columns) * cell_size + Point2i(MARGIN, MARGIN), cell_size - Point2i(MARGIN, MARGIN) * 2); + monitor_draw->draw_style_box(graph_style_box, rect); + + rect.position += graph_style_box->get_offset(); + rect.size -= graph_style_box->get_minimum_size(); + Color draw_color = get_theme_color("accent_color", "Editor"); + draw_color.set_hsv(Math::fmod(hue_shift * float(current.frame_index), 0.9f), draw_color.get_s() * 0.9f, draw_color.get_v() * value_multiplier, 0.6f); + monitor_draw->draw_string(graph_font, rect.position + Point2(0, graph_font->get_ascent()), current.item->get_text(0), draw_color, rect.size.x); + + draw_color.a = 0.9f; + float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1)).width; + if (value_position < 0) { + value_position = 0; + } + monitor_draw->draw_string(graph_font, rect.position + Point2(value_position, graph_font->get_ascent()), current.item->get_text(1), draw_color, rect.size.x); + + rect.position.y += graph_font->get_height(); + rect.size.height -= graph_font->get_height(); + + int line_count = rect.size.height / (graph_font->get_height() * 2); + if (line_count > 5) { + line_count = 5; + } + if (line_count > 0) { + Color horizontal_line_color; + horizontal_line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.5f, draw_color.get_v() * 0.5f, 0.3f); + monitor_draw->draw_line(rect.position, rect.position + Vector2(rect.size.width, 0), horizontal_line_color, Math::round(EDSCALE)); + monitor_draw->draw_string(graph_font, rect.position + Vector2(0, graph_font->get_ascent()), _create_label(current.max, current.type), horizontal_line_color, rect.size.width); + + for (int j = 0; j < line_count; j++) { + Vector2 y_offset = Vector2(0, rect.size.height * (1.0f - float(j) / float(line_count))); + monitor_draw->draw_line(rect.position + y_offset, rect.position + Vector2(rect.size.width, 0) + y_offset, horizontal_line_color, Math::round(EDSCALE)); + monitor_draw->draw_string(graph_font, rect.position - Vector2(0, graph_font->get_descent()) + y_offset, _create_label(current.max * float(j) / float(line_count), current.type), horizontal_line_color, rect.size.width); + } + } + + float from = rect.size.width; + float prev = -1.0f; + int count = 0; + List<float>::Element *e = current.history.front(); + + while (from >= 0 && e) { + float m = current.max; + float h2 = 0; + if (m != 0) { + h2 = (e->get() / m); + } + h2 = (1.0f - h2) * float(rect.size.y); + if (e != current.history.front()) { + monitor_draw->draw_line(rect.position + Point2(from, h2), rect.position + Point2(from + spacing, prev), draw_color, Math::round(EDSCALE)); + } + + if (marker_key == active[i] && count == marker_frame) { + Color line_color; + line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.8f, draw_color.get_v(), 0.5f); + monitor_draw->draw_line(rect.position + Point2(from, 0), rect.position + Point2(from, rect.size.y), line_color, Math::round(EDSCALE)); + + String label = _create_label(e->get(), current.type); + Size2 size = graph_font->get_string_size(label); + Vector2 text_top_left_position = Vector2(from, h2) - (size + Vector2(MARKER_MARGIN, MARKER_MARGIN)); + if (text_top_left_position.x < 0) { + text_top_left_position.x = from + MARKER_MARGIN; + } + if (text_top_left_position.y < 0) { + text_top_left_position.y = h2 + MARKER_MARGIN; + } + monitor_draw->draw_string(graph_font, rect.position + text_top_left_position + Point2(0, graph_font->get_ascent()), label, line_color, rect.size.x); + } + prev = h2; + e = e->next(); + from -= spacing; + count++; + } + } +} + +void EditorPerformanceProfiler::_build_monitor_tree() { + Set<StringName> monitor_checked; + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (i.value().item && i.value().item->is_checked(0)) { + monitor_checked.insert(i.key()); + } + } + + base_map.clear(); + monitor_tree->get_root()->clear_children(); + + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + TreeItem *base = _get_monitor_base(i.value().base); + TreeItem *item = _create_monitor_item(i.value().name, base); + item->set_checked(0, monitor_checked.has(i.key())); + i.value().item = item; + if (!i.value().history.empty()) { + i.value().update_value(i.value().history.front()->get()); + } + } +} + +TreeItem *EditorPerformanceProfiler::_get_monitor_base(const StringName &p_base_name) { + if (base_map.has(p_base_name)) { + return base_map[p_base_name]; + } + + TreeItem *base = monitor_tree->create_item(monitor_tree->get_root()); + base->set_text(0, p_base_name); + base->set_editable(0, false); + base->set_selectable(0, false); + base->set_expand_right(0, true); + base_map.insert(p_base_name, base); + return base; +} + +TreeItem *EditorPerformanceProfiler::_create_monitor_item(const StringName &p_monitor_name, TreeItem *p_base) { + TreeItem *item = monitor_tree->create_item(p_base); + item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); + item->set_editable(0, true); + item->set_selectable(0, false); + item->set_selectable(1, false); + item->set_text(0, p_monitor_name); + return item; +} + +void EditorPerformanceProfiler::_marker_input(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + Vector<StringName> active; + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (i.value().item->is_checked(0)) { + active.push_back(i.key()); + } + } + if (active.size() > 0) { + int columns = int(Math::ceil(Math::sqrt(float(active.size())))); + int rows = int(Math::ceil(float(active.size()) / float(columns))); + if (active.size() == 1) { + rows = 1; + } + Size2i cell_size = Size2i(monitor_draw->get_size()) / Size2i(columns, rows); + Vector2i index = mb->get_position() / cell_size; + Rect2i rect(index * cell_size + Point2i(MARGIN, MARGIN), cell_size - Point2i(MARGIN, MARGIN) * 2); + if (rect.has_point(mb->get_position())) { + if (index.x + index.y * columns < active.size()) { + marker_key = active[index.x + index.y * columns]; + } else { + marker_key = ""; + } + Ref<StyleBox> graph_style_box = get_theme_stylebox("normal", "TextEdit"); + rect.position += graph_style_box->get_offset(); + rect.size -= graph_style_box->get_minimum_size(); + Vector2 point = mb->get_position() - rect.position; + if (point.x >= rect.size.x) { + marker_frame = 0; + } else { + int point_sep = 5; + float spacing = float(point_sep) / float(columns); + marker_frame = (rect.size.x - point.x) / spacing; + } + monitor_draw->update(); + return; + } + } + marker_key = ""; + monitor_draw->update(); + } +} + +void EditorPerformanceProfiler::reset() { + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (String(i.key()).begins_with("custom:")) { + monitors.erase(i); + } else { + i.value().reset(); + } + } + + _build_monitor_tree(); + marker_key = ""; + marker_frame = 0; + monitor_draw->update(); +} + +void EditorPerformanceProfiler::update_monitors(const Vector<StringName> &p_names) { + OrderedHashMap<StringName, int> names; + for (int i = 0; i < p_names.size(); i++) { + names.insert("custom:" + p_names[i], Performance::MONITOR_MAX + i); + } + + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + if (String(i.key()).begins_with("custom:")) { + if (!names.has(i.key())) { + monitors.erase(i); + } else { + i.value().frame_index = names[i.key()]; + names.erase(i.key()); + } + } + } + + for (OrderedHashMap<StringName, int>::Element i = names.front(); i; i = i.next()) { + String name = String(i.key()).replace_first("custom:", ""); + String base = "Custom"; + if (name.get_slice_count("/") == 2) { + base = name.get_slicec('/', 0); + name = name.get_slicec('/', 1); + } + monitors.insert(i.key(), Monitor(name, base, i.value(), Performance::MONITOR_TYPE_QUANTITY, nullptr)); + } + + _build_monitor_tree(); +} + +void EditorPerformanceProfiler::add_profile_frame(const Vector<float> &p_values) { + for (OrderedHashMap<StringName, Monitor>::Element i = monitors.front(); i; i = i.next()) { + float data = 0.0f; + if (i.value().frame_index >= 0 && i.value().frame_index < p_values.size()) { + data = p_values[i.value().frame_index]; + } + i.value().history.push_front(data); + i.value().update_value(data); + } + marker_frame++; + monitor_draw->update(); +} + +List<float> *EditorPerformanceProfiler::get_monitor_data(const StringName &p_name) { + if (monitors.has(p_name)) { + return &monitors[p_name].history; + } + return nullptr; +} + +EditorPerformanceProfiler::EditorPerformanceProfiler() { + set_name(TTR("Monitors")); + set_split_offset(340 * EDSCALE); + + monitor_tree = memnew(Tree); + monitor_tree->set_columns(2); + monitor_tree->set_column_title(0, TTR("Monitor")); + monitor_tree->set_column_title(1, TTR("Value")); + monitor_tree->set_column_titles_visible(true); + monitor_tree->connect("item_edited", callable_mp(this, &EditorPerformanceProfiler::_monitor_select)); + monitor_tree->create_item(); + monitor_tree->set_hide_root(true); + add_child(monitor_tree); + + monitor_draw = memnew(Control); + monitor_draw->set_clip_contents(true); + monitor_draw->connect("draw", callable_mp(this, &EditorPerformanceProfiler::_monitor_draw)); + monitor_draw->connect("gui_input", callable_mp(this, &EditorPerformanceProfiler::_marker_input)); + add_child(monitor_draw); + + info_message = memnew(Label); + info_message->set_text(TTR("Pick one or more items from the list to display the graph.")); + info_message->set_valign(Label::VALIGN_CENTER); + info_message->set_align(Label::ALIGN_CENTER); + info_message->set_autowrap(true); + info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); + info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + monitor_draw->add_child(info_message); + + for (int i = 0; i < Performance::MONITOR_MAX; i++) { + String base = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)).get_slicec('/', 0).capitalize(); + String name = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)).get_slicec('/', 1).capitalize(); + monitors.insert(Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)), Monitor(name, base, i, Performance::get_singleton()->get_monitor_type(Performance::Monitor(i)), nullptr)); + } + + _build_monitor_tree(); +} diff --git a/editor/debugger/editor_performance_profiler.h b/editor/debugger/editor_performance_profiler.h new file mode 100644 index 0000000000..144dd34103 --- /dev/null +++ b/editor/debugger/editor_performance_profiler.h @@ -0,0 +1,90 @@ +/*************************************************************************/ +/* editor_performance_profiler.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 EDITOR_PERFORMANCE_PROFILER_H +#define EDITOR_PERFORMANCE_PROFILER_H + +#include "core/map.h" +#include "core/ordered_hash_map.h" +#include "main/performance.h" +#include "scene/gui/control.h" +#include "scene/gui/label.h" +#include "scene/gui/split_container.h" +#include "scene/gui/tree.h" + +class EditorPerformanceProfiler : public HSplitContainer { + GDCLASS(EditorPerformanceProfiler, HSplitContainer); + +private: + class Monitor { + public: + String name; + String base; + List<float> history; + float max = 0.0f; + TreeItem *item = nullptr; + Performance::MonitorType type = Performance::MONITOR_TYPE_QUANTITY; + int frame_index = 0; + + Monitor(); + Monitor(String p_name, String p_base, int p_frame_index, Performance::MonitorType p_type, TreeItem *p_item); + void update_value(float p_value); + void reset(); + }; + + OrderedHashMap<StringName, Monitor> monitors; + + Map<StringName, TreeItem *> base_map; + Tree *monitor_tree; + Control *monitor_draw; + Label *info_message; + StringName marker_key; + int marker_frame; + const int MARGIN = 4; + const int POINT_SEPARATION = 5; + const int MARKER_MARGIN = 2; + + static String _create_label(float p_value, Performance::MonitorType p_type); + void _monitor_select(); + void _monitor_draw(); + void _build_monitor_tree(); + TreeItem *_get_monitor_base(const StringName &p_base_name); + TreeItem *_create_monitor_item(const StringName &p_monitor_name, TreeItem *p_base); + void _marker_input(const Ref<InputEvent> &p_event); + +public: + void reset(); + void update_monitors(const Vector<StringName> &p_names); + void add_profile_frame(const Vector<float> &p_values); + List<float> *get_monitor_data(const StringName &p_name); + EditorPerformanceProfiler(); +}; + +#endif // EDITOR_PERFORMANCE_PROFILER_H diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 6b010fbfb5..a828e29558 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -36,6 +36,7 @@ #include "core/project_settings.h" #include "core/ustring.h" #include "editor/debugger/editor_network_profiler.h" +#include "editor/debugger/editor_performance_profiler.h" #include "editor/debugger/editor_profiler.h" #include "editor/debugger/editor_visual_profiler.h" #include "editor/editor_log.h" @@ -172,14 +173,25 @@ void ScriptEditorDebugger::_file_selected(const String &p_file) { file->store_csv_line(line); // values - List<Vector<float>>::Element *E = perf_history.back(); - while (E) { - Vector<float> &perf_data = E->get(); - for (int i = 0; i < perf_data.size(); i++) { - line.write[i] = String::num_real(perf_data[i]); + Vector<List<float>::Element *> iterators; + iterators.resize(Performance::MONITOR_MAX); + bool continue_iteration = false; + for (int i = 0; i < Performance::MONITOR_MAX; i++) { + iterators.write[i] = performance_profiler->get_monitor_data(Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)))->back(); + continue_iteration = continue_iteration || iterators[i]; + } + while (continue_iteration) { + continue_iteration = false; + for (int i = 0; i < Performance::MONITOR_MAX; i++) { + if (iterators[i]) { + line.write[i] = String::num_real(iterators[i]->get()); + iterators.write[i] = iterators[i]->prev(); + } else { + line.write[i] = ""; + } + continue_iteration = continue_iteration || iterators[i]; } file->store_csv_line(line); - E = E->prev(); } file->store_string("\n"); @@ -409,37 +421,12 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da EditorNode::get_log()->add_message(output_strings[i], msg_type); } } else if (p_msg == "performance:profile_frame") { - Vector<float> p; - p.resize(p_data.size()); + Vector<float> frame_data; + frame_data.resize(p_data.size()); for (int i = 0; i < p_data.size(); i++) { - p.write[i] = p_data[i]; - if (i < perf_items.size()) { - const float value = p[i]; - String label = rtos(value); - String tooltip = label; - switch (Performance::MonitorType((int)perf_items[i]->get_metadata(1))) { - case Performance::MONITOR_TYPE_MEMORY: { - label = String::humanize_size(value); - tooltip = label; - } break; - case Performance::MONITOR_TYPE_TIME: { - label = rtos(value * 1000).pad_decimals(2) + " ms"; - tooltip = label; - } break; - default: { - tooltip += " " + perf_items[i]->get_text(0); - } break; - } - - perf_items[i]->set_text(1, label); - perf_items[i]->set_tooltip(1, tooltip); - if (p[i] > perf_max[i]) { - perf_max.write[i] = p[i]; - } - } + frame_data.write[i] = p_data[i]; } - perf_history.push_front(p); - perf_draw->update(); + performance_profiler->add_profile_frame(frame_data); } else if (p_msg == "visual:profile_frame") { DebuggerMarshalls::VisualProfilerFrame frame; @@ -704,6 +691,15 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da emit_signal("stop_requested"); _stop_and_notify(); + } else if (p_msg == "performance:profile_names") { + Vector<StringName> monitors; + monitors.resize(p_data.size()); + for (int i = 0; i < p_data.size(); i++) { + ERR_FAIL_COND(p_data[i].get_type() != Variant::STRING_NAME); + monitors.set(i, p_data[i]); + } + performance_profiler->update_monitors(monitors); + } else { WARN_PRINT("unknown message " + p_msg); } @@ -724,141 +720,6 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType reason->set_tooltip(p_reason.word_wrap(80)); } -void ScriptEditorDebugger::_performance_select() { - perf_draw->update(); -} - -void ScriptEditorDebugger::_performance_draw() { - Vector<int> which; - for (int i = 0; i < perf_items.size(); i++) { - if (perf_items[i]->is_checked(0)) { - which.push_back(i); - } - } - - if (which.empty()) { - info_message->show(); - return; - } - - info_message->hide(); - - const Ref<StyleBox> graph_sb = get_theme_stylebox("normal", "TextEdit"); - const Ref<Font> graph_font = get_theme_font("font", "TextEdit"); - - const int cols = Math::ceil(Math::sqrt((float)which.size())); - int rows = Math::ceil((float)which.size() / cols); - if (which.size() == 1) { - rows = 1; - } - - const int margin = 3; - const int point_sep = 5; - const Size2i s = Size2i(perf_draw->get_size()) / Size2i(cols, rows); - - for (int i = 0; i < which.size(); i++) { - Point2i p(i % cols, i / cols); - Rect2i r(p * s, s); - r.position += Point2(margin, margin); - r.size -= Point2(margin, margin) * 2.0; - perf_draw->draw_style_box(graph_sb, r); - r.position += graph_sb->get_offset(); - r.size -= graph_sb->get_minimum_size(); - const int pi = which[i]; - - // Draw horizontal lines with labels. - - int nb_lines = 5; - // Draw less lines if the monitor isn't tall enough to display 5 labels. - if (r.size.height <= 160 * EDSCALE) { - nb_lines = 3; - } else if (r.size.height <= 240 * EDSCALE) { - nb_lines = 4; - } - - const float inv_nb_lines = 1.0 / nb_lines; - - for (int line = 0; line < nb_lines; line += 1) { - const int from_x = r.position.x; - const int to_x = r.position.x + r.size.width; - const int y = r.position.y + (r.size.height * inv_nb_lines + line * inv_nb_lines * r.size.height); - perf_draw->draw_line( - Point2(from_x, y), - Point2i(to_x, y), - Color(0.5, 0.5, 0.5, 0.25), - Math::round(EDSCALE)); - - String label; - switch (Performance::MonitorType((int)perf_items[pi]->get_metadata(1))) { - case Performance::MONITOR_TYPE_MEMORY: { - label = String::humanize_size(Math::ceil((1 - inv_nb_lines - inv_nb_lines * line) * perf_max[pi])); - } break; - case Performance::MONITOR_TYPE_TIME: { - label = rtos((1 - inv_nb_lines - inv_nb_lines * line) * perf_max[pi] * 1000).pad_decimals(2) + " ms"; - } break; - default: { - label = itos(Math::ceil((1 - inv_nb_lines - inv_nb_lines * line) * perf_max[pi])); - } break; - } - - perf_draw->draw_string( - graph_font, - Point2(from_x, y - graph_font->get_ascent() * 0.25), - label, - Color(0.5, 0.5, 0.5, 1.0)); - } - - const float h = (float)which[i] / (float)(perf_items.size()); - // Use a darker color on light backgrounds for better visibility. - const float value_multiplier = EditorSettings::get_singleton()->is_dark_theme() ? 1.4 : 0.55; - Color color = get_theme_color("accent_color", "Editor"); - color.set_hsv(Math::fmod(h + 0.4, 0.9), color.get_s() * 0.9, color.get_v() * value_multiplier); - - // Draw the monitor name in the top-left corner. - color.a = 0.6; - perf_draw->draw_string( - graph_font, - r.position + Point2(0, graph_font->get_ascent()), - perf_items[pi]->get_text(0), - color, - r.size.x); - - // Draw the monitor value in the top-left corner, just below the name. - color.a = 0.9; - perf_draw->draw_string( - graph_font, - r.position + Point2(0, graph_font->get_ascent() + graph_font->get_height()), - perf_items[pi]->get_text(1), - color, - r.size.y); - - const float spacing = point_sep / float(cols); - float from = r.size.width; - - const List<Vector<float>>::Element *E = perf_history.front(); - float prev = -1; - while (from >= 0 && E) { - float m = perf_max[pi]; - if (m == 0) { - m = 0.00001; - } - float h2 = E->get()[pi] / m; - h2 = (1.0 - h2) * r.size.y; - - if (E != perf_history.front()) { - perf_draw->draw_line( - r.position + Point2(from, h2), - r.position + Point2(from + spacing, prev), - color, - Math::round(EDSCALE)); - } - prev = h2; - E = E->next(); - from -= spacing; - } - } -} - void ScriptEditorDebugger::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -976,10 +837,7 @@ void ScriptEditorDebugger::start(Ref<RemoteDebuggerPeer> p_peer) { peer = p_peer; ERR_FAIL_COND(p_peer.is_null()); - perf_history.clear(); - for (int i = 0; i < Performance::MONITOR_MAX; i++) { - perf_max.write[i] = 0; - } + performance_profiler->reset(); set_process(true); breaked = false; @@ -1727,63 +1585,8 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { } { //monitors - - HSplitContainer *hsp = memnew(HSplitContainer); - - perf_monitors = memnew(Tree); - perf_monitors->set_columns(2); - perf_monitors->set_column_title(0, TTR("Monitor")); - perf_monitors->set_column_title(1, TTR("Value")); - perf_monitors->set_column_titles_visible(true); - perf_monitors->connect("item_edited", callable_mp(this, &ScriptEditorDebugger::_performance_select)); - hsp->add_child(perf_monitors); - - perf_draw = memnew(Control); - perf_draw->set_clip_contents(true); - perf_draw->connect("draw", callable_mp(this, &ScriptEditorDebugger::_performance_draw)); - hsp->add_child(perf_draw); - - hsp->set_name(TTR("Monitors")); - hsp->set_split_offset(340 * EDSCALE); - tabs->add_child(hsp); - perf_max.resize(Performance::MONITOR_MAX); - - Map<String, TreeItem *> bases; - TreeItem *root = perf_monitors->create_item(); - perf_monitors->set_hide_root(true); - for (int i = 0; i < Performance::MONITOR_MAX; i++) { - String n = Performance::get_singleton()->get_monitor_name(Performance::Monitor(i)); - Performance::MonitorType mtype = Performance::get_singleton()->get_monitor_type(Performance::Monitor(i)); - String base = n.get_slice("/", 0); - String name = n.get_slice("/", 1); - if (!bases.has(base)) { - TreeItem *b = perf_monitors->create_item(root); - b->set_text(0, base.capitalize()); - b->set_editable(0, false); - b->set_selectable(0, false); - b->set_expand_right(0, true); - bases[base] = b; - } - - TreeItem *it = perf_monitors->create_item(bases[base]); - it->set_metadata(1, mtype); - it->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); - it->set_editable(0, true); - it->set_selectable(0, false); - it->set_selectable(1, false); - it->set_text(0, name.capitalize()); - perf_items.push_back(it); - perf_max.write[i] = 0; - } - - info_message = memnew(Label); - info_message->set_text(TTR("Pick one or more items from the list to display the graph.")); - info_message->set_valign(Label::VALIGN_CENTER); - info_message->set_align(Label::ALIGN_CENTER); - info_message->set_autowrap(true); - info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); - perf_draw->add_child(info_message); + performance_profiler = memnew(EditorPerformanceProfiler); + tabs->add_child(performance_profiler); } { //vmem inspect diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index 2984051aa1..12fb82cc6f 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -52,6 +52,7 @@ class ItemList; class EditorProfiler; class EditorVisualProfiler; class EditorNetworkProfiler; +class EditorPerformanceProfiler; class SceneDebuggerTree; class ScriptEditorDebugger : public MarginContainer { @@ -113,16 +114,8 @@ private: // Each debugger should have it's tree in the future I guess. const Tree *editor_remote_tree = nullptr; - List<Vector<float>> perf_history; - Vector<float> perf_max; - Vector<TreeItem *> perf_items; - Map<int, String> profiler_signature; - Tree *perf_monitors; - Control *perf_draw; - Label *info_message; - Tree *vmem_tree; Button *vmem_refresh; Button *vmem_export; @@ -141,6 +134,7 @@ private: EditorProfiler *profiler; EditorVisualProfiler *visual_profiler; EditorNetworkProfiler *network_profiler; + EditorPerformanceProfiler *performance_profiler; EditorNode *editor; @@ -152,8 +146,6 @@ private: EditorDebuggerNode::CameraOverride camera_override; - void _performance_draw(); - void _performance_select(); void _stack_dump_frame_selected(); void _file_selected(const String &p_file); diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp index b43ee0e245..edb299bb90 100644 --- a/editor/editor_asset_installer.cpp +++ b/editor/editor_asset_installer.cpp @@ -159,7 +159,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) { isdir = true; } - int pp = path.find_last("/"); + int pp = path.rfind("/"); TreeItem *parent; if (pp == -1) { diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 2a410c03e7..0d349eb247 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -335,7 +335,7 @@ void EditorFeatureProfileManager::_update_profile_list(const String &p_select_pr } if (!d->current_is_dir()) { - int last_pos = f.find_last(".profile"); + int last_pos = f.rfind(".profile"); if (last_pos != -1) { profiles.push_back(f.substr(0, last_pos)); } diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 663f3dd856..eb4c587122 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -936,7 +936,7 @@ void EditorFileDialog::set_current_file(const String &p_file) { file->set_text(p_file); update_dir(); invalidate(); - int lp = p_file.find_last("."); + int lp = p_file.rfind("."); if (lp != -1) { file->select(0, lp); file->grab_focus(); @@ -951,7 +951,7 @@ void EditorFileDialog::set_current_path(const String &p_path) { if (!p_path.size()) { return; } - int pos = MAX(p_path.find_last("/"), p_path.find_last("\\")); + int pos = MAX(p_path.rfind("/"), p_path.rfind("\\")); if (pos == -1) { set_current_file(p_path); } else { diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index d88c61d7b2..9ca3d387d9 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -233,9 +233,9 @@ void EditorFileSystem::_scan_filesystem() { FileCache fc; fc.type = split[1]; - fc.modification_time = split[2].to_int64(); - fc.import_modification_time = split[3].to_int64(); - fc.import_valid = split[4].to_int64() != 0; + fc.modification_time = split[2].to_int(); + fc.import_modification_time = split[3].to_int(); + fc.import_valid = split[4].to_int() != 0; fc.import_group_file = split[5].strip_edges(); fc.script_class_name = split[6].get_slice("<>", 0); fc.script_class_extends = split[6].get_slice("<>", 1); diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index f0e6e3a799..a7e76e9b2b 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -251,7 +251,7 @@ void EditorFolding::_do_object_unfolds(Object *p_object, Set<RES> &resources) { } } } else { //path - int last = E->get().name.find_last("/"); + int last = E->get().name.rfind("/"); if (last != -1) { bool can_revert = EditorPropertyRevert::can_property_revert(p_object, E->get().name); if (can_revert) { diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index d2b9405552..4392538737 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -332,17 +332,10 @@ bool EditorHelpSearch::Runner::_phase_match_classes() { if (search_flags & SEARCH_METHODS) { for (int i = 0; i < class_doc.methods.size(); i++) { String method_name = (search_flags & SEARCH_CASE_SENSITIVE) ? class_doc.methods[i].name : class_doc.methods[i].name.to_lower(); - String aux_term = (search_flags & SEARCH_CASE_SENSITIVE) ? term : term.to_lower(); - - if (aux_term.begins_with(".")) { - aux_term = aux_term.right(1); - } - - if (aux_term.ends_with("(")) { - aux_term = aux_term.left(aux_term.length() - 1).strip_edges(); - } - - if (aux_term.is_subsequence_of(method_name)) { + if (method_name.find(term) > -1 || + (term.begins_with(".") && method_name.begins_with(term.right(1))) || + (term.ends_with("(") && method_name.ends_with(term.left(term.length() - 1).strip_edges())) || + (term.begins_with(".") && term.ends_with("(") && method_name == term.substr(1, term.length() - 2).strip_edges())) { match.methods.push_back(const_cast<DocData::MethodDoc *>(&class_doc.methods[i])); } } @@ -448,9 +441,9 @@ bool EditorHelpSearch::Runner::_phase_select_match() { bool EditorHelpSearch::Runner::_match_string(const String &p_term, const String &p_string) const { if (search_flags & SEARCH_CASE_SENSITIVE) { - return p_term.is_subsequence_of(p_string); + return p_string.find(p_term) > -1; } else { - return p_term.is_subsequence_ofi(p_string); + return p_string.findn(p_term) > -1; } } diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index a8ded44323..7742382048 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1504,9 +1504,9 @@ void EditorInspector::update_tree() { String subgroup_base; VBoxContainer *category_vbox = nullptr; - List<PropertyInfo> - plist; + List<PropertyInfo> plist; object->get_property_list(&plist, true); + _update_script_class_properties(*object, plist); HashMap<String, VBoxContainer *> item_path; Map<VBoxContainer *, EditorInspectorSection *> section_map; @@ -1572,7 +1572,28 @@ void EditorInspector::update_tree() { category_vbox = nullptr; //reset String type = p.name; - category->icon = EditorNode::get_singleton()->get_class_icon(type, "Object"); + if (!ClassDB::class_exists(type) && !ScriptServer::is_global_class(type) && p.hint_string.length() && FileAccess::exists(p.hint_string)) { + Ref<Script> s = ResourceLoader::load(p.hint_string, "Script"); + String base_type; + if (s.is_valid()) { + base_type = s->get_instance_base_type(); + } + while (s.is_valid()) { + StringName name = EditorNode::get_editor_data().script_class_get_name(s->get_path()); + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); + if (name != StringName() && icon_path.length()) { + category->icon = ResourceLoader::load(icon_path, "Texture"); + break; + } + s = s->get_base_script(); + } + if (category->icon.is_null() && has_theme_icon(base_type, "EditorIcons")) { + category->icon = get_theme_icon(base_type, "EditorIcons"); + } + } + if (category->icon.is_null()) { + category->icon = EditorNode::get_singleton()->get_class_icon(type, "Object"); + } category->label = type; category->bg_color = get_theme_color("prop_category", "Editor"); @@ -1643,7 +1664,7 @@ void EditorInspector::update_tree() { basename = group + "/" + basename; } - String name = (basename.find("/") != -1) ? basename.right(basename.find_last("/") + 1) : basename; + String name = (basename.find("/") != -1) ? basename.right(basename.rfind("/") + 1) : basename; if (capitalize_paths) { int dot = name.find("."); @@ -1658,7 +1679,7 @@ void EditorInspector::update_tree() { } } - String path = basename.left(basename.find_last("/")); + String path = basename.left(basename.rfind("/")); if (use_filter && filter != "") { String cat = path; @@ -2370,6 +2391,83 @@ void EditorInspector::_feature_profile_changed() { update_tree(); } +void EditorInspector::_update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const { + Ref<Script> script = p_object.get_script(); + if (script.is_null()) { + return; + } + + List<StringName> classes; + Map<StringName, String> paths; + + // NodeC -> NodeB -> NodeA + while (script.is_valid()) { + String n = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + if (n.length()) { + classes.push_front(n); + } else { + n = script->get_path().get_file(); + classes.push_front(n); + } + paths[n] = script->get_path(); + script = script->get_base_script(); + } + + if (classes.empty()) { + return; + } + + // Script Variables -> to insert: NodeC..B..A -> bottom (insert_here) + List<PropertyInfo>::Element *script_variables = NULL; + List<PropertyInfo>::Element *bottom = NULL; + List<PropertyInfo>::Element *insert_here = NULL; + for (List<PropertyInfo>::Element *E = r_list.front(); E; E = E->next()) { + PropertyInfo &pi = E->get(); + if (pi.name != "Script Variables") { + continue; + } + script_variables = E; + bottom = r_list.insert_after(script_variables, PropertyInfo()); + insert_here = bottom; + break; + } + + Set<StringName> added; + for (List<StringName>::Element *E = classes.front(); E; E = E->next()) { + StringName name = E->get(); + String path = paths[name]; + Ref<Script> s = ResourceLoader::load(path, "Script"); + List<PropertyInfo> props; + s->get_script_property_list(&props); + + // Script Variables -> NodeA -> bottom (insert_here) + List<PropertyInfo>::Element *category = r_list.insert_before(insert_here, PropertyInfo(Variant::NIL, name, PROPERTY_HINT_NONE, path, PROPERTY_USAGE_CATEGORY)); + + // Script Variables -> NodeA -> A props... -> bottom (insert_here) + for (List<PropertyInfo>::Element *P = props.front(); P; P = P->next()) { + PropertyInfo &pi = P->get(); + if (added.has(pi.name)) { + continue; + } + added.insert(pi.name); + + r_list.insert_before(insert_here, pi); + } + + // Script Variables -> NodeA (insert_here) -> A props... -> bottom + insert_here = category; + } + + // NodeC -> C props... -> NodeB..C.. + r_list.erase(script_variables); + List<PropertyInfo>::Element *to_delete = bottom->next(); + while (to_delete && !(to_delete->get().usage & PROPERTY_USAGE_CATEGORY)) { + r_list.erase(to_delete); + to_delete = bottom->next(); + } + r_list.erase(bottom); +} + void EditorInspector::_bind_methods() { ClassDB::bind_method("_edit_request_change", &EditorInspector::_edit_request_change); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 90d995e36d..615ad97766 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -332,6 +332,7 @@ class EditorInspector : public ScrollContainer { void _vscroll_changed(double); void _feature_profile_changed(); + void _update_script_class_properties(const Object &p_object, List<PropertyInfo> &r_list) const; bool _is_property_disabled_by_feature_profile(const StringName &p_property); diff --git a/editor/editor_log.h b/editor/editor_log.h index 3bf5615346..73a8c3f0c5 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -32,7 +32,6 @@ #define EDITOR_LOG_H #include "core/os/thread.h" -#include "pane_drag.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/control.h" @@ -50,7 +49,6 @@ class EditorLog : public VBoxContainer { Label *title; RichTextLabel *log; HBoxContainer *title_hb; - //PaneDrag *pd; Button *tool_button; static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d8bc555d6d..6e65103748 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -85,6 +85,7 @@ #include "editor/editor_settings.h" #include "editor/editor_spin_slider.h" #include "editor/editor_themes.h" +#include "editor/editor_translation_parser.h" #include "editor/export_template_manager.h" #include "editor/filesystem_dock.h" #include "editor/import/editor_import_collada.h" @@ -103,7 +104,6 @@ #include "editor/import_dock.h" #include "editor/multi_node_edit.h" #include "editor/node_dock.h" -#include "editor/pane_drag.h" #include "editor/plugin_config_dialog.h" #include "editor/plugins/animation_blend_space_1d_editor.h" #include "editor/plugins/animation_blend_space_2d_editor.h" @@ -138,6 +138,7 @@ #include "editor/plugins/multimesh_editor_plugin.h" #include "editor/plugins/navigation_polygon_editor_plugin.h" #include "editor/plugins/node_3d_editor_plugin.h" +#include "editor/plugins/packed_scene_translation_parser_plugin.h" #include "editor/plugins/path_2d_editor_plugin.h" #include "editor/plugins/path_3d_editor_plugin.h" #include "editor/plugins/physical_bone_3d_editor_plugin.h" @@ -178,6 +179,111 @@ EditorNode *EditorNode::singleton = nullptr; +void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) { + // Keep track of a list of "index sets," i.e. sets of indices + // within disambiguated_scene_names which contain the same name. + Vector<Set<int>> index_sets; + Map<String, int> scene_name_to_set_index; + for (int i = 0; i < r_filenames.size(); i++) { + String scene_name = r_filenames[i]; + if (!scene_name_to_set_index.has(scene_name)) { + index_sets.append(Set<int>()); + scene_name_to_set_index.insert(r_filenames[i], index_sets.size() - 1); + } + index_sets.write[scene_name_to_set_index[scene_name]].insert(i); + } + + // For each index set with a size > 1, we need to disambiguate + for (int i = 0; i < index_sets.size(); i++) { + Set<int> iset = index_sets[i]; + while (iset.size() > 1) { + // Append the parent folder to each scene name + for (Set<int>::Element *E = iset.front(); E; E = E->next()) { + int set_idx = E->get(); + String scene_name = r_filenames[set_idx]; + String full_path = p_full_paths[set_idx]; + + // Get rid of file extensions and res:// prefixes + if (scene_name.rfind(".") >= 0) { + scene_name = scene_name.substr(0, scene_name.rfind(".")); + } + if (full_path.begins_with("res://")) { + full_path = full_path.substr(6); + } + if (full_path.rfind(".") >= 0) { + full_path = full_path.substr(0, full_path.rfind(".")); + } + + int scene_name_size = scene_name.size(); + int full_path_size = full_path.size(); + int difference = full_path_size - scene_name_size; + + // Find just the parent folder of the current path and append it. + // If the current name is foo.tscn, and the full path is /some/folder/foo.tscn + // then slash_idx is the second '/', so that we select just "folder", and + // append that to yield "folder/foo.tscn". + if (difference > 0) { + String parent = full_path.substr(0, difference); + int slash_idx = parent.rfind("/"); + slash_idx = parent.rfind("/", slash_idx - 1); + parent = slash_idx >= 0 ? parent.substr(slash_idx + 1) : parent; + r_filenames.write[set_idx] = parent + r_filenames[set_idx]; + } + } + + // Loop back through scene names and remove non-ambiguous names + bool can_proceed = false; + Set<int>::Element *E = iset.front(); + while (E) { + String scene_name = r_filenames[E->get()]; + bool duplicate_found = false; + for (Set<int>::Element *F = iset.front(); F; F = F->next()) { + if (E->get() == F->get()) { + continue; + } + String other_scene_name = r_filenames[F->get()]; + if (other_scene_name == scene_name) { + duplicate_found = true; + break; + } + } + + Set<int>::Element *to_erase = duplicate_found ? nullptr : E; + + // We need to check that we could actually append anymore names + // if we wanted to for disambiguation. If we can't, then we have + // to abort even with ambiguous names. We clean the full path + // and the scene name first to remove extensions so that this + // comparison actually works. + String path = p_full_paths[E->get()]; + if (path.begins_with("res://")) { + path = path.substr(6); + } + if (path.rfind(".") >= 0) { + path = path.substr(0, path.rfind(".")); + } + if (scene_name.rfind(".") >= 0) { + scene_name = scene_name.substr(0, scene_name.rfind(".")); + } + + // We can proceed iff the full path is longer than the scene name, + // meaning that there is at least one more parent folder we can + // tack onto the name. + can_proceed = can_proceed || (path.size() - scene_name.size()) >= 1; + + E = E->next(); + if (to_erase) { + iset.erase(to_erase); + } + } + + if (!can_proceed) { + break; + } + } + } +} + void EditorNode::_update_scene_tabs() { bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button"); @@ -185,6 +291,16 @@ void EditorNode::_update_scene_tabs() { DisplayServer::get_singleton()->global_menu_clear("_dock"); } + // Get all scene names, which may be ambiguous + Vector<String> disambiguated_scene_names; + Vector<String> full_path_names; + for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { + disambiguated_scene_names.append(editor_data.get_scene_title(i)); + full_path_names.append(editor_data.get_scene_path(i)); + } + + disambiguate_filenames(full_path_names, disambiguated_scene_names); + scene_tabs->clear_tabs(); Ref<Texture2D> script_icon = gui_base->get_theme_icon("Script", "EditorIcons"); for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { @@ -196,7 +312,7 @@ void EditorNode::_update_scene_tabs() { int current = editor_data.get_edited_scene(); bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; - scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon); + scene_tabs->add_tab(disambiguated_scene_names[i] + (unsaved ? "(*)" : ""), icon); if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) { DisplayServer::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), callable_mp(this, &EditorNode::_global_menu_scene), i); @@ -360,7 +476,7 @@ void EditorNode::_notification(int p_what) { bool dof_jitter = GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter"); RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter); RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); - RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_curve")); + RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"), GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit")); bool glow_bicubic = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0; RS::get_singleton()->environment_glow_set_use_bicubic_upscale(glow_bicubic); RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality"))); @@ -376,6 +492,12 @@ void EditorNode::_notification(int p_what) { RS::get_singleton()->directional_shadow_quality_set(directional_shadow_quality); float probe_update_speed = GLOBAL_GET("rendering/lightmapper/probe_capture_update_speed"); RS::get_singleton()->lightmap_set_probe_capture_update_speed(probe_update_speed); + RS::EnvironmentSDFGIFramesToConverge frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(int(GLOBAL_GET("rendering/sdfgi/frames_to_converge"))); + RS::get_singleton()->environment_set_sdfgi_frames_to_converge(frames_to_converge); + RS::EnvironmentSDFGIRayCount ray_count = RS::EnvironmentSDFGIRayCount(int(GLOBAL_GET("rendering/sdfgi/probe_ray_count"))); + RS::get_singleton()->environment_set_sdfgi_ray_count(ray_count); + RS::GIProbeQuality gi_probe_quality = RS::GIProbeQuality(int(GLOBAL_GET("rendering/quality/gi_probes/quality"))); + RS::get_singleton()->gi_probe_set_quality(gi_probe_quality); } ResourceImporterTexture::get_singleton()->update_imports(); @@ -429,14 +551,14 @@ void EditorNode::_notification(int p_what) { /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_APPLICATION_FOCUS_IN: { // Restore the original FPS cap after focusing back on the editor OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec"))); EditorFileSystem::get_singleton()->scan_changes(); } break; - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_APPLICATION_FOCUS_OUT: { // Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec"))); } break; @@ -3405,10 +3527,14 @@ void EditorNode::_update_recent_scenes() { void EditorNode::_quick_opened() { Vector<String> files = quick_open->get_selected_files(); + bool open_scene_dialog = quick_open->get_base_type() == "PackedScene"; for (int i = 0; i < files.size(); i++) { String res_path = files[i]; - if (quick_open->get_base_type() == "PackedScene") { + List<String> scene_extensions; + ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions); + + if (open_scene_dialog || scene_extensions.find(files[i].get_extension())) { open_request(res_path); } else { load_resource(res_path); @@ -3464,6 +3590,7 @@ void EditorNode::register_editor_types() { ResourceSaver::set_timestamp_on_save(true); ClassDB::register_class<EditorPlugin>(); + ClassDB::register_class<EditorTranslationParserPlugin>(); ClassDB::register_class<EditorImportPlugin>(); ClassDB::register_class<EditorScript>(); ClassDB::register_class<EditorSelection>(); @@ -3637,16 +3764,13 @@ Ref<Texture2D> EditorNode::get_object_icon(const Object *p_object, const String Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p_fallback) const { ERR_FAIL_COND_V_MSG(p_class.empty(), nullptr, "Class name cannot be empty."); - if (gui_base->has_theme_icon(p_class, "EditorIcons")) { - return gui_base->get_theme_icon(p_class, "EditorIcons"); - } - if (ScriptServer::is_global_class(p_class)) { Ref<ImageTexture> icon; Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class); + StringName name = p_class; while (script.is_valid()) { - StringName name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); icon = _load_custom_class_icon(current_icon_path); if (icon.is_valid()) { @@ -3656,10 +3780,8 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } if (icon.is_null()) { - icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(p_class), "EditorIcons"); + icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(name), "EditorIcons"); } - - return icon; } const Map<String, Vector<EditorData::CustomType>> &p_map = EditorNode::get_editor_data().get_custom_types(); @@ -3674,6 +3796,10 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p } } + if (gui_base->has_theme_icon(p_class, "EditorIcons")) { + return gui_base->get_theme_icon(p_class, "EditorIcons"); + } + if (p_fallback.length() && gui_base->has_theme_icon(p_fallback, "EditorIcons")) { return gui_base->get_theme_icon(p_fallback, "EditorIcons"); } @@ -4152,7 +4278,6 @@ void EditorNode::_update_dock_slots_visibility() { } right_hsplit->hide(); - bottom_panel->hide(); } else { for (int i = 0; i < DOCK_SLOT_MAX; i++) { int tabs_visible = 0; @@ -4182,7 +4307,6 @@ void EditorNode::_update_dock_slots_visibility() { dock_slot[i]->set_current_tab(0); } } - bottom_panel->show(); if (right_l_vsplit->is_visible() || right_r_vsplit->is_visible()) { right_hsplit->show(); @@ -6483,6 +6607,7 @@ EditorNode::EditorNode() { } resource_preview->add_preview_generator(Ref<EditorTexturePreviewPlugin>(memnew(EditorTexturePreviewPlugin))); + resource_preview->add_preview_generator(Ref<EditorImagePreviewPlugin>(memnew(EditorImagePreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorPackedScenePreviewPlugin>(memnew(EditorPackedScenePreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorMaterialPreviewPlugin>(memnew(EditorMaterialPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorScriptPreviewPlugin>(memnew(EditorScriptPreviewPlugin))); @@ -6534,6 +6659,10 @@ EditorNode::EditorNode() { EditorExport::get_singleton()->add_export_plugin(export_text_to_binary_plugin); + Ref<PackedSceneEditorTranslationParserPlugin> packed_scene_translation_parser_plugin; + packed_scene_translation_parser_plugin.instance(); + EditorTranslationParser::get_singleton()->add_parser(packed_scene_translation_parser_plugin, EditorTranslationParser::STANDARD); + _edit_current(); current = nullptr; saving_resource = Ref<Resource>(); diff --git a/editor/editor_node.h b/editor/editor_node.h index b0e0c5614c..f6cae466ff 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -71,7 +71,6 @@ class ImportDock; class MenuButton; class NodeDock; class OrphanResourcesDialog; -class PaneDrag; class Panel; class PanelContainer; class PluginConfigDialog; @@ -255,7 +254,6 @@ private: VSplitContainer *top_split; HBoxContainer *bottom_hb; Control *vp_base; - PaneDrag *pd; HBoxContainer *menu_hb; Control *viewport; @@ -687,6 +685,8 @@ public: static void add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); static void remove_editor_plugin(EditorPlugin *p_editor, bool p_config_changed = false); + static void disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames); + void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); } void set_docks_visible(bool p_show); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 32b799cd61..af1b426327 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -663,6 +663,14 @@ bool EditorPlugin::get_remove_list(List<Node *> *p_list) { void EditorPlugin::restore_global_state() {} void EditorPlugin::save_global_state() {} +void EditorPlugin::add_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser) { + EditorTranslationParser::get_singleton()->add_parser(p_parser, EditorTranslationParser::CUSTOM); +} + +void EditorPlugin::remove_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser) { + EditorTranslationParser::get_singleton()->remove_parser(p_parser, EditorTranslationParser::CUSTOM); +} + void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) { ResourceFormatImporter::get_singleton()->add_importer(p_importer); EditorFileSystem::get_singleton()->call_deferred("scan"); @@ -796,6 +804,8 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_undo_redo"), &EditorPlugin::_get_undo_redo); ClassDB::bind_method(D_METHOD("queue_save_layout"), &EditorPlugin::queue_save_layout); + ClassDB::bind_method(D_METHOD("add_translation_parser_plugin", "parser"), &EditorPlugin::add_translation_parser_plugin); + ClassDB::bind_method(D_METHOD("remove_translation_parser_plugin", "parser"), &EditorPlugin::remove_translation_parser_plugin); ClassDB::bind_method(D_METHOD("add_import_plugin", "importer"), &EditorPlugin::add_import_plugin); ClassDB::bind_method(D_METHOD("remove_import_plugin", "importer"), &EditorPlugin::remove_import_plugin); ClassDB::bind_method(D_METHOD("add_scene_import_plugin", "scene_importer"), &EditorPlugin::add_scene_import_plugin); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index e84984d57a..52ff7f04f8 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -34,6 +34,7 @@ #include "core/io/config_file.h" #include "core/undo_redo.h" #include "editor/editor_inspector.h" +#include "editor/editor_translation_parser.h" #include "editor/import/editor_import_plugin.h" #include "editor/import/resource_importer_scene.h" #include "editor/script_create_dialog.h" @@ -220,6 +221,9 @@ public: virtual void restore_global_state(); virtual void save_global_state(); + void add_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser); + void remove_translation_parser_plugin(const Ref<EditorTranslationParserPlugin> &p_parser); + void add_import_plugin(const Ref<EditorImportPlugin> &p_importer); void remove_import_plugin(const Ref<EditorImportPlugin> &p_importer); diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index b5f1133a9e..fe49198e8f 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -39,7 +39,7 @@ #include "scene/gui/margin_container.h" void EditorPluginSettings::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { update_plugins(); } else if (p_what == Node::NOTIFICATION_READY) { plugin_config_dialog->connect_compat("plugin_ready", EditorNode::get_singleton(), "_on_plugin_ready"); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index eee610e9a8..8f9c92ea15 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -377,13 +377,13 @@ void EditorPropertyMember::_property_select() { selector->select_method_from_base_type(hint_text, current); } else if (hint == MEMBER_METHOD_OF_INSTANCE) { - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { selector->select_method_from_instance(instance, current); } } else if (hint == MEMBER_METHOD_OF_SCRIPT) { - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { selector->select_method_from_script(Object::cast_to<Script>(obj), current); } @@ -408,13 +408,13 @@ void EditorPropertyMember::_property_select() { selector->select_property_from_base_type(hint_text, current); } else if (hint == MEMBER_PROPERTY_OF_INSTANCE) { - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { selector->select_property_from_instance(instance, current); } } else if (hint == MEMBER_PROPERTY_OF_SCRIPT) { - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { selector->select_property_from_script(Object::cast_to<Script>(obj), current); } @@ -488,7 +488,7 @@ void EditorPropertyEnum::setup(const Vector<String> &p_options) { for (int i = 0; i < p_options.size(); i++) { Vector<String> text_split = p_options[i].split(":"); if (text_split.size() != 1) { - current_val = text_split[1].to_int64(); + current_val = text_split[1].to_int(); } options->add_item(text_split[0]); options->set_item_metadata(i, current_val); @@ -2983,8 +2983,16 @@ bool EditorPropertyResource::_is_drop_valid(const Dictionary &p_drag_data) const String allowed_type = base_type; Dictionary drag_data = p_drag_data; - if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - Ref<Resource> res = drag_data["resource"]; + + Ref<Resource> res; + if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); + res = se->get_edited_resource(); + } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + res = drag_data["resource"]; + } + + if (res.is_valid()) { for (int i = 0; i < allowed_type.get_slice_count(","); i++) { String at = allowed_type.get_slice(",", i).strip_edges(); if (res.is_valid() && ClassDB::is_parent_class(res->get_class(), at)) { @@ -3022,13 +3030,19 @@ void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant & ERR_FAIL_COND(!_is_drop_valid(p_data)); Dictionary drag_data = p_data; - if (drag_data.has("type") && String(drag_data["type"]) == "resource") { - Ref<Resource> res = drag_data["resource"]; - if (res.is_valid()) { - emit_changed(get_edited_property(), res); - update_property(); - return; - } + + Ref<Resource> res; + if (drag_data.has("type") && String(drag_data["type"]) == "script_list_element") { + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(drag_data["script_list_element"]); + res = se->get_edited_resource(); + } else if (drag_data.has("type") && String(drag_data["type"]) == "resource") { + res = drag_data["resource"]; + } + + if (res.is_valid()) { + emit_changed(get_edited_property(), res); + update_property(); + return; } if (drag_data.has("type") && String(drag_data["type"]) == "files") { @@ -3036,9 +3050,9 @@ void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant & if (files.size() == 1) { String file = files[0]; - RES res = ResourceLoader::load(file); - if (res.is_valid()) { - emit_changed(get_edited_property(), res); + RES file_res = ResourceLoader::load(file); + if (file_res.is_valid()) { + emit_changed(get_edited_property(), file_res); update_property(); return; } diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 7ac8fae156..d2250fed7a 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -110,7 +110,7 @@ void EditorResourcePreview::_preview_ready(const String &p_str, const Ref<Textur uint64_t modified_time = 0; if (p_str.begins_with("ID:")) { - hash = uint32_t(p_str.get_slicec(':', 2).to_int64()); + hash = uint32_t(p_str.get_slicec(':', 2).to_int()); path = "ID:" + p_str.get_slicec(':', 1); } else { modified_time = FileAccess::get_modified_time(path); @@ -257,9 +257,9 @@ void EditorResourcePreview::_thread() { _generate_preview(texture, small_texture, item, cache_base); } else { uint64_t modtime = FileAccess::get_modified_time(item.path); - int tsize = f->get_line().to_int64(); + int tsize = f->get_line().to_int(); bool has_small_texture = f->get_line().to_int(); - uint64_t last_modtime = f->get_line().to_int64(); + uint64_t last_modtime = f->get_line().to_int(); bool cache_valid = true; diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 67d92c4839..d76a3d2da7 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -182,8 +182,8 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) { } void EditorSpinSlider::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_OUT || - p_what == NOTIFICATION_WM_FOCUS_IN || + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_OUT || + p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN || p_what == NOTIFICATION_EXIT_TREE) { if (grabbing_spinner) { grabber->hide(); diff --git a/editor/editor_translation_parser.cpp b/editor/editor_translation_parser.cpp new file mode 100644 index 0000000000..1f08a985f1 --- /dev/null +++ b/editor/editor_translation_parser.cpp @@ -0,0 +1,180 @@ +/*************************************************************************/ +/* editor_translation_parser.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "editor_translation_parser.h" + +#include "core/error_macros.h" +#include "core/os/file_access.h" +#include "core/script_language.h" +#include "core/set.h" + +EditorTranslationParser *EditorTranslationParser::singleton = nullptr; + +Error EditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_extracted_strings) { + if (!get_script_instance()) + return ERR_UNAVAILABLE; + + if (get_script_instance()->has_method("parse_text")) { + Error err; + FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &err); + if (err != OK) { + ERR_PRINT("Failed to open " + p_path); + return err; + } + parse_text(file->get_as_utf8_string(), r_extracted_strings); + return OK; + } else { + ERR_PRINT("Custom translation parser plugin's \"func parse_text(text, extracted_strings)\" is undefined."); + return ERR_UNAVAILABLE; + } +} + +void EditorTranslationParserPlugin::parse_text(const String &p_text, Vector<String> *r_extracted_strings) { + if (!get_script_instance()) + return; + + if (get_script_instance()->has_method("parse_text")) { + Array extracted_strings; + get_script_instance()->call("parse_text", p_text, extracted_strings); + for (int i = 0; i < extracted_strings.size(); i++) { + r_extracted_strings->append(extracted_strings[i]); + } + } else { + ERR_PRINT("Custom translation parser plugin's \"func parse_text(text, extracted_strings)\" is undefined."); + } +} + +void EditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { + if (!get_script_instance()) + return; + + if (get_script_instance()->has_method("get_recognized_extensions")) { + Array extensions = get_script_instance()->call("get_recognized_extensions"); + for (int i = 0; i < extensions.size(); i++) { + r_extensions->push_back(extensions[i]); + } + } else { + ERR_PRINT("Custom translation parser plugin's \"func get_recognized_extensions()\" is undefined."); + } +} + +void EditorTranslationParserPlugin::_bind_methods() { + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::NIL, "parse_text", PropertyInfo(Variant::STRING, "text"), PropertyInfo(Variant::ARRAY, "extracted_strings"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::ARRAY, "get_recognized_extensions")); +} + +///////////////////////// + +void EditorTranslationParser::get_recognized_extensions(List<String> *r_extensions) const { + Set<String> extensions; + List<String> temp; + for (int i = 0; i < standard_parsers.size(); i++) { + standard_parsers[i]->get_recognized_extensions(&temp); + } + for (int i = 0; i < custom_parsers.size(); i++) { + custom_parsers[i]->get_recognized_extensions(&temp); + } + // Remove duplicates. + for (int i = 0; i < temp.size(); i++) { + extensions.insert(temp[i]); + } + for (auto E = extensions.front(); E; E = E->next()) { + r_extensions->push_back(E->get()); + } +} + +bool EditorTranslationParser::can_parse(const String &p_extension) const { + List<String> extensions; + get_recognized_extensions(&extensions); + for (int i = 0; i < extensions.size(); i++) { + if (p_extension == extensions[i]) { + return true; + } + } + return false; +} + +Ref<EditorTranslationParserPlugin> EditorTranslationParser::get_parser(const String &p_extension) const { + // Consider user-defined parsers first. + for (int i = 0; i < custom_parsers.size(); i++) { + List<String> temp; + custom_parsers[i]->get_recognized_extensions(&temp); + for (int j = 0; j < temp.size(); j++) { + if (temp[j] == p_extension) { + return custom_parsers[i]; + } + } + } + + for (int i = 0; i < standard_parsers.size(); i++) { + List<String> temp; + standard_parsers[i]->get_recognized_extensions(&temp); + for (int j = 0; j < temp.size(); j++) { + if (temp[j] == p_extension) { + return standard_parsers[i]; + } + } + } + + WARN_PRINT("No translation parser available for \"" + p_extension + "\" extension."); + + return nullptr; +} + +void EditorTranslationParser::add_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type) { + if (p_type == ParserType::STANDARD) { + standard_parsers.push_back(p_parser); + } else if (p_type == ParserType::CUSTOM) { + custom_parsers.push_back(p_parser); + } +} + +void EditorTranslationParser::remove_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type) { + if (p_type == ParserType::STANDARD) { + standard_parsers.erase(p_parser); + } else if (p_type == ParserType::CUSTOM) { + custom_parsers.erase(p_parser); + } +} + +EditorTranslationParser *EditorTranslationParser::get_singleton() { + if (!singleton) { + singleton = memnew(EditorTranslationParser); + } + return singleton; +} + +EditorTranslationParser::EditorTranslationParser() { +} + +EditorTranslationParser::~EditorTranslationParser() { + memdelete(singleton); + singleton = nullptr; +} diff --git a/editor/editor_translation_parser.h b/editor/editor_translation_parser.h new file mode 100644 index 0000000000..518e3616eb --- /dev/null +++ b/editor/editor_translation_parser.h @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* editor_translation_parser.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 EDITOR_TRANSLATION_PARSER_H +#define EDITOR_TRANSLATION_PARSER_H + +#include "core/error_list.h" +#include "core/reference.h" + +class EditorTranslationParserPlugin : public Reference { + GDCLASS(EditorTranslationParserPlugin, Reference); + +protected: + static void _bind_methods(); + +public: + virtual Error parse_file(const String &p_path, Vector<String> *r_extracted_strings); + virtual void parse_text(const String &p_text, Vector<String> *r_extracted_strings); + virtual void get_recognized_extensions(List<String> *r_extensions) const; +}; + +class EditorTranslationParser { + static EditorTranslationParser *singleton; + +public: + enum ParserType { + STANDARD, // GDScript, CSharp, ... + CUSTOM // User-defined parser plugins. This will override standard parsers if the same extension type is defined. + }; + + static EditorTranslationParser *get_singleton(); + + Vector<Ref<EditorTranslationParserPlugin>> standard_parsers; + Vector<Ref<EditorTranslationParserPlugin>> custom_parsers; + + void get_recognized_extensions(List<String> *r_extensions) const; + bool can_parse(const String &p_extension) const; + Ref<EditorTranslationParserPlugin> get_parser(const String &p_extension) const; + void add_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type); + void remove_parser(const Ref<EditorTranslationParserPlugin> &p_parser, ParserType p_type); + + EditorTranslationParser(); + ~EditorTranslationParser(); +}; + +#endif // EDITOR_TRANSLATION_PARSER_H diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index c700fdccad..4f37fcf39c 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -1688,7 +1688,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected String name = to_rename.path.get_file(); rename_dialog->set_title(TTR("Renaming file:") + " " + name); rename_dialog_text->set_text(name); - rename_dialog_text->select(0, name.find_last(".")); + rename_dialog_text->select(0, name.rfind(".")); } else { String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file(); rename_dialog->set_title(TTR("Renaming folder:") + " " + name); @@ -1732,7 +1732,7 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected String name = to_duplicate.path.get_file(); duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name); duplicate_dialog_text->set_text(name); - duplicate_dialog_text->select(0, name.find_last(".")); + duplicate_dialog_text->select(0, name.rfind(".")); } else { String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file(); duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name); @@ -2313,7 +2313,7 @@ void FileSystemDock::_tree_rmb_select(const Vector2 &p_pos) { tree_popup->clear(); tree_popup->set_size(Size2(1, 1)); _file_and_folders_fill_popup(tree_popup, paths); - tree_popup->set_position(tree->get_global_position() + p_pos); + tree_popup->set_position(tree->get_screen_position() + p_pos); tree_popup->popup(); } } @@ -2508,10 +2508,10 @@ void FileSystemDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_tree_thumbnail_done"), &FileSystemDock::_tree_thumbnail_done); ClassDB::bind_method(D_METHOD("_select_file"), &FileSystemDock::_select_file); - ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &FileSystemDock::get_drag_data_fw); - ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &FileSystemDock::can_drop_data_fw); - ClassDB::bind_method(D_METHOD("drop_data_fw"), &FileSystemDock::drop_data_fw); - ClassDB::bind_method(D_METHOD("navigate_to_path"), &FileSystemDock::navigate_to_path); + ClassDB::bind_method(D_METHOD("get_drag_data_fw", "position", "from"), &FileSystemDock::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("can_drop_data_fw", "position", "data", "from"), &FileSystemDock::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw", "position", "data", "from"), &FileSystemDock::drop_data_fw); + ClassDB::bind_method(D_METHOD("navigate_to_path", "path"), &FileSystemDock::navigate_to_path); ClassDB::bind_method(D_METHOD("_update_import_dock"), &FileSystemDock::_update_import_dock); diff --git a/editor/icons/InterpolatedCamera.svg b/editor/icons/InterpolatedCamera.svg deleted file mode 100644 index 4bc4ba1ee9..0000000000 --- a/editor/icons/InterpolatedCamera.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9.5.00004c-1.5691.0017903-2.8718 1.2125-2.9883 2.7773-.55103-.49952-1.268-.77655-2.0117-.77734-1.6569 0-3 1.3431-3 3 .00179 1.2698.80282 2.4009 2 2.8242v2.1758c0 .554.44599 1 1 1h6c.55401 0 .9853-.4462 1-1v-1l3 2v-6l-3 2v-1.7695c.63486-.56783.99842-1.3788 1-2.2305 0-1.6569-1.3431-3-3-3zm-6 12v4h1v-4zm3 0v4h1v-1h1c.55228 0 1-.44772 1-1v-1c0-.55228-.44824-1.024-1-1h-1zm5 0c-.55228 0-1 .44772-1 1v2c0 .55228.44772 1 1 1h1c.55228 0 1-.44772 1-1v-2c0-.55228-.44772-1-1-1zm-4 1h1v1h-1zm4 0h1v2h-1z" fill="#fc9c9c"/></svg>
\ No newline at end of file diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 65ebf9dc4f..5dcdf6bec4 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -943,9 +943,9 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String ERR_CONTINUE(anim.is_null()); if (!p_animations.has(anim)) { - // We are making external files so they are modifiable + // Tracks from source file should be set as imported, anything else is a custom track. for (int i = 0; i < anim->get_track_count(); i++) { - anim->track_set_imported(i, false); + anim->track_set_imported(i, true); } String ext_name; @@ -957,10 +957,9 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String } if (FileAccess::exists(ext_name) && p_keep_animations) { - //try to keep custom animation tracks + // Copy custom animation tracks from previously imported files. Ref<Animation> old_anim = ResourceLoader::load(ext_name, "Animation", true); if (old_anim.is_valid()) { - //meergeee for (int i = 0; i < old_anim->get_track_count(); i++) { if (!old_anim->track_is_imported(i)) { old_anim->copy_track(i, anim); @@ -970,7 +969,7 @@ void ResourceImporterScene::_make_external_resources(Node *p_node, const String } } - anim->set_path(ext_name, true); //if not set, then its never saved externally + anim->set_path(ext_name, true); // Set path to save externally. ResourceSaver::save(ext_name, anim, ResourceSaver::FLAG_CHANGE_PATH); p_animations[anim] = anim; } diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index e99ffe2b83..49e67f3605 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -369,7 +369,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } else { const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); - if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { + if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(xform.xform(cpoint)) < grab_threshold) { //wip closed _wip_close(); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 035526ca55..1312f59a70 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -710,11 +710,11 @@ void AnimationPlayerEditor::_dialog_action(String p_file) { Ref<Resource> res = ResourceLoader::load(p_file, "Animation"); ERR_FAIL_COND_MSG(res.is_null(), "Cannot load Animation from file '" + p_file + "'."); ERR_FAIL_COND_MSG(!res->is_class("Animation"), "Loaded resource from file '" + p_file + "' is not Animation."); - if (p_file.find_last("/") != -1) { - p_file = p_file.substr(p_file.find_last("/") + 1, p_file.length()); + if (p_file.rfind("/") != -1) { + p_file = p_file.substr(p_file.rfind("/") + 1, p_file.length()); } - if (p_file.find_last("\\") != -1) { - p_file = p_file.substr(p_file.find_last("\\") + 1, p_file.length()); + if (p_file.rfind("\\") != -1) { + p_file = p_file.substr(p_file.rfind("\\") + 1, p_file.length()); } if (p_file.find(".") != -1) { diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp index ec3e25f999..dc813896ff 100644 --- a/editor/plugins/animation_tree_editor_plugin.cpp +++ b/editor/plugins/animation_tree_editor_plugin.cpp @@ -238,7 +238,7 @@ AnimationTreeEditor::AnimationTreeEditor() { add_child(memnew(HSeparator)); singleton = this; - editor_base = memnew(PanelContainer); + editor_base = memnew(MarginContainer); editor_base->set_v_size_flags(SIZE_EXPAND_FILL); add_child(editor_base); diff --git a/editor/plugins/animation_tree_editor_plugin.h b/editor/plugins/animation_tree_editor_plugin.h index 25af81ea9b..79a010b0c0 100644 --- a/editor/plugins/animation_tree_editor_plugin.h +++ b/editor/plugins/animation_tree_editor_plugin.h @@ -55,7 +55,7 @@ class AnimationTreeEditor : public VBoxContainer { HBoxContainer *path_hb; AnimationTree *tree; - PanelContainer *editor_base; + MarginContainer *editor_base; Vector<String> button_path; Vector<String> edited_path; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index e35cbfcfb0..3af0b0d4e1 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -6149,6 +6149,11 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point); target_pos = canvas_item_editor->snap_point(target_pos); target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); + // Preserve instance position of the original scene. + CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instanced_scene); + if (instance_ci) { + target_pos += instance_ci->_edit_get_position(); + } editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); } diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 596629f8e8..105ac24950 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -242,9 +242,11 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { } break; case CONCAVE_POLYGON_SHAPE: { + // Cannot be edited directly, use CollisionPolygon2D instead. } break; case CONVEX_POLYGON_SHAPE: { + // Cannot be edited directly, use CollisionPolygon2D instead. } break; case LINE_SHAPE: { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index ebd9c7f070..b51ea9e1c6 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -487,6 +487,10 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b Vector3 pos = _get_ray_pos(p_pos); Vector2 shrinked_pos = p_pos / subviewport_container->get_stretch_shrink(); + if (viewport->get_debug_draw() == Viewport::DEBUG_DRAW_SDFGI_PROBES) { + RS::get_singleton()->sdfgi_set_debug_probe_select(pos, ray); + } + Vector<ObjectID> instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world_3d()->get_scenario()); Set<Ref<EditorNode3DGizmo>> found_gizmos; @@ -2984,7 +2988,9 @@ void Node3DEditorViewport::_menu_option(int p_option) { case VIEW_DISPLAY_DEBUG_SSAO: case VIEW_DISPLAY_DEBUG_PSSM_SPLITS: case VIEW_DISPLAY_DEBUG_DECAL_ATLAS: - case VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER: { + case VIEW_DISPLAY_DEBUG_SDFGI: + case VIEW_DISPLAY_DEBUG_SDFGI_PROBES: + case VIEW_DISPLAY_DEBUG_GI_BUFFER: { static const int display_options[] = { VIEW_DISPLAY_NORMAL, VIEW_DISPLAY_WIREFRAME, @@ -3000,9 +3006,11 @@ void Node3DEditorViewport::_menu_option(int p_option) { VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, - VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER, + VIEW_DISPLAY_DEBUG_GI_BUFFER, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, VIEW_DISPLAY_DEBUG_DECAL_ATLAS, + VIEW_DISPLAY_DEBUG_SDFGI, + VIEW_DISPLAY_DEBUG_SDFGI_PROBES, VIEW_MAX }; static const Viewport::DebugDraw debug_draw_modes[] = { @@ -3020,9 +3028,11 @@ void Node3DEditorViewport::_menu_option(int p_option) { Viewport::DEBUG_DRAW_GI_PROBE_EMISSION, Viewport::DEBUG_DRAW_SCENE_LUMINANCE, Viewport::DEBUG_DRAW_SSAO, - Viewport::DEBUG_DRAW_ROUGHNESS_LIMITER, + Viewport::DEBUG_DRAW_GI_BUFFER, Viewport::DEBUG_DRAW_PSSM_SPLITS, Viewport::DEBUG_DRAW_DECAL_ATLAS, + Viewport::DEBUG_DRAW_SDFGI, + Viewport::DEBUG_DRAW_SDFGI_PROBES, }; int idx = 0; @@ -3898,11 +3908,14 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito display_submenu->add_radio_check_item(TTR("GIProbe Albedo"), VIEW_DISPLAY_DEBUG_GIPROBE_ALBEDO); display_submenu->add_radio_check_item(TTR("GIProbe Emission"), VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION); display_submenu->add_separator(); + display_submenu->add_radio_check_item(TTR("SDFGI Cascades"), VIEW_DISPLAY_DEBUG_SDFGI); + display_submenu->add_radio_check_item(TTR("SDFGI Probes"), VIEW_DISPLAY_DEBUG_SDFGI_PROBES); + display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("Scene Luminance"), VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE); display_submenu->add_separator(); display_submenu->add_radio_check_item(TTR("SSAO"), VIEW_DISPLAY_DEBUG_SSAO); display_submenu->add_separator(); - display_submenu->add_radio_check_item(TTR("Roughness Limiter"), VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER); + display_submenu->add_radio_check_item(TTR("GI Buffer"), VIEW_DISPLAY_DEBUG_GI_BUFFER); display_submenu->set_name("display_advanced"); view_menu->get_popup()->add_submenu_item(TTR("Display Advanced..."), "display_advanced", VIEW_DISPLAY_ADVANCED); view_menu->get_popup()->add_separator(); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 2fe1938f28..a40de78795 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -214,9 +214,11 @@ class Node3DEditorViewport : public Control { VIEW_DISPLAY_DEBUG_GIPROBE_EMISSION, VIEW_DISPLAY_DEBUG_SCENE_LUMINANCE, VIEW_DISPLAY_DEBUG_SSAO, - VIEW_DISPLAY_DEBUG_ROUGHNESS_LIMITER, VIEW_DISPLAY_DEBUG_PSSM_SPLITS, VIEW_DISPLAY_DEBUG_DECAL_ATLAS, + VIEW_DISPLAY_DEBUG_SDFGI, + VIEW_DISPLAY_DEBUG_SDFGI_PROBES, + VIEW_DISPLAY_DEBUG_GI_BUFFER, VIEW_LOCK_ROTATION, VIEW_CINEMATIC_PREVIEW, VIEW_AUTO_ORTHOGONAL, diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp new file mode 100644 index 0000000000..f9aaa93614 --- /dev/null +++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp @@ -0,0 +1,114 @@ +/*************************************************************************/ +/* packed_scene_translation_parser_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "packed_scene_translation_parser_plugin.h" + +#include "core/io/resource_loader.h" +#include "scene/resources/packed_scene.h" + +void PackedSceneEditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { + ResourceLoader::get_recognized_extensions_for_type("PackedScene", r_extensions); +} + +Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_extracted_strings) { + // Parse specific scene Node's properties (see in constructor) that are auto-translated by the engine when set. E.g Label's text property. + // These properties are translated with the tr() function in the C++ code when being set or updated. + + Error err; + RES loaded_res = ResourceLoader::load(p_path, "PackedScene", false, &err); + if (err) { + ERR_PRINT("Failed to load " + p_path); + return err; + } + Ref<SceneState> state = Ref<PackedScene>(loaded_res)->get_state(); + + Vector<String> parsed_strings; + String property_name; + Variant property_value; + for (int i = 0; i < state->get_node_count(); i++) { + if (!ClassDB::is_parent_class(state->get_node_type(i), "Control") && !ClassDB::is_parent_class(state->get_node_type(i), "Viewport")) { + continue; + } + + for (int j = 0; j < state->get_node_property_count(i); j++) { + property_name = state->get_node_property_name(i, j); + if (!lookup_properties.has(property_name)) { + continue; + } + + property_value = state->get_node_property_value(i, j); + + if (property_name == "script" && property_value.get_type() == Variant::OBJECT && !property_value.is_null()) { + // Parse built-in script. + Ref<Script> s = Object::cast_to<Script>(property_value); + String extension = s->get_language()->get_extension(); + if (EditorTranslationParser::get_singleton()->can_parse(extension)) { + Vector<String> temp; + EditorTranslationParser::get_singleton()->get_parser(extension)->parse_text(s->get_source_code(), &temp); + parsed_strings.append_array(temp); + } + } else if (property_name == "filters") { + // Extract FileDialog's filters property with values in format "*.png ; PNG Images","*.gd ; GDScript Files". + Vector<String> str_values = property_value; + for (int k = 0; k < str_values.size(); k++) { + String desc = str_values[k].get_slice(";", 1).strip_edges(); + if (!desc.empty()) { + parsed_strings.push_back(desc); + } + } + } else if (property_value.get_type() == Variant::STRING) { + String str_value = String(property_value); + // Prevent reading text containing only spaces. + if (!str_value.strip_edges().empty()) { + parsed_strings.push_back(str_value); + } + } + } + } + + r_extracted_strings->append_array(parsed_strings); + + return OK; +} + +PackedSceneEditorTranslationParserPlugin::PackedSceneEditorTranslationParserPlugin() { + // Scene Node's properties containing strings that will be fetched for translation. + lookup_properties.insert("text"); + lookup_properties.insert("hint_tooltip"); + lookup_properties.insert("placeholder_text"); + lookup_properties.insert("dialog_text"); + lookup_properties.insert("filters"); + lookup_properties.insert("script"); + + //Add exception list (to prevent false positives) + //line edit, text edit, richtextlabel + //Set<String> exception_list; + //exception_list.insert("RichTextLabel"); +} diff --git a/editor/pane_drag.cpp b/editor/plugins/packed_scene_translation_parser_plugin.h index 09f2b90b90..9fead84c3f 100644 --- a/editor/pane_drag.cpp +++ b/editor/plugins/packed_scene_translation_parser_plugin.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pane_drag.cpp */ +/* packed_scene_translation_parser_plugin.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,48 +28,22 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "pane_drag.h" +#ifndef PACKED_SCENE_TRANSLATION_PARSER_PLUGIN_H +#define PACKED_SCENE_TRANSLATION_PARSER_PLUGIN_H -void PaneDrag::_gui_input(const Ref<InputEvent> &p_input) { - Ref<InputEventMouseMotion> mm = p_input; - if (mm.is_valid() && mm->get_button_mask() & BUTTON_MASK_LEFT) { - emit_signal("dragged", Point2(mm->get_relative().x, mm->get_relative().y)); - } -} +#include "editor/editor_translation_parser.h" -void PaneDrag::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_DRAW: { - Ref<Texture2D> icon = mouse_over ? get_theme_icon("PaneDragHover", "EditorIcons") : get_theme_icon("PaneDrag", "EditorIcons"); - if (!icon.is_null()) { - icon->draw(get_canvas_item(), Point2(0, 0)); - } +class PackedSceneEditorTranslationParserPlugin : public EditorTranslationParserPlugin { + GDCLASS(PackedSceneEditorTranslationParserPlugin, EditorTranslationParserPlugin); - } break; - case NOTIFICATION_MOUSE_ENTER: - mouse_over = true; - update(); - break; - case NOTIFICATION_MOUSE_EXIT: - mouse_over = false; - update(); - break; - } -} + // Scene Node's properties that contain translation strings. + Set<String> lookup_properties; -Size2 PaneDrag::get_minimum_size() const { - Ref<Texture2D> icon = get_theme_icon("PaneDrag", "EditorIcons"); - if (!icon.is_null()) { - return icon->get_size(); - } - return Size2(); -} +public: + virtual Error parse_file(const String &p_path, Vector<String> *r_extracted_strings); + virtual void get_recognized_extensions(List<String> *r_extensions) const; -void PaneDrag::_bind_methods() { - ClassDB::bind_method("_gui_input", &PaneDrag::_gui_input); - ADD_SIGNAL(MethodInfo("dragged", PropertyInfo(Variant::VECTOR2, "amount"))); -} + PackedSceneEditorTranslationParserPlugin(); +}; -PaneDrag::PaneDrag() { - mouse_over = false; -} +#endif // PACKED_SCENE_TRANSLATION_PARSER_PLUGIN_H diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 96079d5418..66f0155c6a 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -538,7 +538,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected)); if (current) { if (p_save) { - apply_scripts(); + _menu_option(FILE_SAVE); } Ref<Script> script = current->get_edited_resource(); @@ -1337,7 +1337,7 @@ void ScriptEditor::_notification(int p_what) { editor->disconnect("stop_pressed", callable_mp(this, &ScriptEditor::_editor_stop)); } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { _test_script_times_on_disk(); _update_modified_scripts_for_external_editor(); } break; @@ -1731,6 +1731,19 @@ void ScriptEditor::_update_script_names() { sedata.push_back(sd); } + Vector<String> disambiguated_script_names; + Vector<String> full_script_paths; + for (int j = 0; j < sedata.size(); j++) { + disambiguated_script_names.append(sedata[j].name); + full_script_paths.append(sedata[j].tooltip); + } + + EditorNode::disambiguate_filenames(full_script_paths, disambiguated_script_names); + + for (int j = 0; j < sedata.size(); j++) { + sedata.write[j].name = disambiguated_script_names[j]; + } + EditorHelp *eh = Object::cast_to<EditorHelp>(tab_container->get_child(i)); if (eh) { String name = eh->get_class(); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 0c3a44e4cd..7dd0b8a238 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -338,7 +338,7 @@ void ShaderEditor::_menu_option(int p_option) { } void ShaderEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { _check_for_external_edit(); } } diff --git a/editor/plugins/shader_file_editor_plugin.cpp b/editor/plugins/shader_file_editor_plugin.cpp index 0ac29f68f6..f15a801530 100644 --- a/editor/plugins/shader_file_editor_plugin.cpp +++ b/editor/plugins/shader_file_editor_plugin.cpp @@ -200,7 +200,7 @@ void ShaderFileEditor::_update_options() { } void ShaderFileEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_WM_FOCUS_IN) { + if (p_what == NOTIFICATION_WM_WINDOW_FOCUS_IN) { if (is_visible_in_tree() && shader_file.is_valid()) { _update_options(); } diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 3a92818779..762f42abeb 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -780,7 +780,7 @@ void TextureRegionEditor::_notification(int p_what) { _update_autoslice(); } } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { // This happens when the user leaves the Editor and returns, // they could have changed the textures, so the cache is cleared. cache_map.clear(); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 158f9e8587..307a8a9001 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -64,6 +64,8 @@ void TileMapEditor::_notification(int p_what) { } paint_button->set_icon(get_theme_icon("Edit", "EditorIcons")); + line_button->set_icon(get_theme_icon("CurveLinear", "EditorIcons")); + rectangle_button->set_icon(get_theme_icon("RectangleShape2D", "EditorIcons")); bucket_fill_button->set_icon(get_theme_icon("Bucket", "EditorIcons")); picker_button->set_icon(get_theme_icon("ColorPick", "EditorIcons")); select_button->set_icon(get_theme_icon("ActionCopy", "EditorIcons")); @@ -91,9 +93,10 @@ void TileMapEditor::_notification(int p_what) { } void TileMapEditor::_update_button_tool() { - Button *tb[4] = { paint_button, bucket_fill_button, picker_button, select_button }; + Button *tb[6] = { paint_button, line_button, rectangle_button, bucket_fill_button, picker_button, select_button }; + // Unpress all buttons - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 6; i++) { tb[i]->set_pressed(false); } @@ -103,6 +106,12 @@ void TileMapEditor::_update_button_tool() { case TOOL_PAINTING: { paint_button->set_pressed(true); } break; + case TOOL_LINE_PAINT: { + line_button->set_pressed(true); + } break; + case TOOL_RECTANGLE_PAINT: { + rectangle_button->set_pressed(true); + } break; case TOOL_BUCKET: { bucket_fill_button->set_pressed(true); } break; @@ -993,19 +1002,8 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { } if (tool == TOOL_NONE) { - if (mb->get_shift()) { - if (mb->get_command()) { - tool = TOOL_RECTANGLE_PAINT; - } else { - tool = TOOL_LINE_PAINT; - } - - selection_active = false; - rectangle_begin = over_tile; - - _update_button_tool(); - return true; - } + tool = TOOL_PAINTING; + _update_button_tool(); if (mb->get_command()) { tool = TOOL_PICKING; @@ -1014,12 +1012,14 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return true; } - - tool = TOOL_PAINTING; - _update_button_tool(); } - if (tool == TOOL_PAINTING) { + if (tool == TOOL_LINE_PAINT || tool == TOOL_RECTANGLE_PAINT) { + selection_active = false; + rectangle_begin = over_tile; + + mouse_down = true; + } else if (tool == TOOL_PAINTING) { Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1050,6 +1050,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { paint_undo.clear(); } } else if (tool == TOOL_LINE_PAINT) { + if (!mouse_down) { + return true; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1062,8 +1066,17 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { paint_undo.clear(); CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } + + mouse_down = false; } else if (tool == TOOL_RECTANGLE_PAINT) { + if (!mouse_down) { + return true; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { @@ -1076,7 +1089,12 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _finish_undo(); CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } + + mouse_down = false; } else if (tool == TOOL_PASTING) { Point2 ofs = over_tile - rectangle.position; Vector<int> ids; @@ -1141,6 +1159,28 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { if (tool == TOOL_PASTING) { tool = TOOL_NONE; + + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + + if (tool == TOOL_LINE_PAINT) { + tool = TOOL_LINE_ERASE; + mouse_down = true; + rectangle_begin = over_tile; + + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + + if (tool == TOOL_RECTANGLE_PAINT) { + tool = TOOL_RECTANGLE_ERASE; + mouse_down = true; + rectangle_begin = over_tile; copydata.clear(); CanvasItemEditor::get_singleton()->update_viewport(); @@ -1155,39 +1195,74 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Point2 local = node->world_to_map(xform_inv.xform(mb->get_position())); _start_undo(TTR("Erase TileMap")); + tool = TOOL_ERASING; + _set_cell(local, invalid_cell); - if (mb->get_shift()) { - if (mb->get_command()) { - tool = TOOL_RECTANGLE_ERASE; - } else { - tool = TOOL_LINE_ERASE; + _update_button_tool(); + return true; + } + + } else { + if (tool == TOOL_LINE_ERASE) { + if (!mouse_down) { + return true; + } + + tool = TOOL_LINE_PAINT; + _update_button_tool(); + + Vector<int> ids = get_selected_tiles(); + + if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { + _start_undo(TTR("Line Erase")); + for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { + _set_cell(E->key(), invalid_cell, flip_h, flip_v, transpose); } + _finish_undo(); + paint_undo.clear(); - selection_active = false; - rectangle_begin = local; - } else { - tool = TOOL_ERASING; + CanvasItemEditor::get_singleton()->update_viewport(); - _set_cell(local, invalid_cell); + mouse_down = false; + return true; } + mouse_down = false; + } else if (tool == TOOL_RECTANGLE_ERASE) { + if (!mouse_down) { + return true; + } + + tool = TOOL_RECTANGLE_PAINT; _update_button_tool(); - return true; - } - } else { - if (tool == TOOL_ERASING || tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { - _finish_undo(); + Vector<int> ids = get_selected_tiles(); + + if (ids.size() > 0 && ids[0] != TileMap::INVALID_CELL) { + _start_undo(TTR("Rectangle Erase")); + for (int i = rectangle.position.y; i <= rectangle.position.y + rectangle.size.y; i++) { + for (int j = rectangle.position.x; j <= rectangle.position.x + rectangle.size.x; j++) { + _set_cell(Point2i(j, i), invalid_cell, flip_h, flip_v, transpose); + } + } + _finish_undo(); + paint_undo.clear(); - if (tool == TOOL_RECTANGLE_ERASE || tool == TOOL_LINE_ERASE) { CanvasItemEditor::get_singleton()->update_viewport(); + + mouse_down = false; + return true; } - tool = TOOL_NONE; + mouse_down = false; + tool = TOOL_RECTANGLE_PAINT; + } + if (tool == TOOL_ERASING) { + tool = TOOL_NONE; _update_button_tool(); - return true; + return true; } else if (tool == TOOL_BUCKET) { Vector<int> ids; ids.push_back(node->get_cell(over_tile.x, over_tile.y)); @@ -1278,6 +1353,10 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Vector<int> tmp_cell; bool erasing = (tool == TOOL_LINE_ERASE); + if (!mouse_down) { + return true; + } + tmp_cell.push_back(0); if (erasing && paint_undo.size()) { for (Map<Point2i, CellOp>::Element *E = paint_undo.front(); E; E = E->next()) { @@ -1308,7 +1387,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Vector<int> tmp_cell; tmp_cell.push_back(0); - _select(rectangle_begin, over_tile); + Point2i end_tile = over_tile; + + if (!mouse_down) { + return true; + } + + if (mm->get_shift()) { + int size = fmax(ABS(end_tile.x - rectangle_begin.x), ABS(end_tile.y - rectangle_begin.y)); + int xDirection = MAX(MIN(end_tile.x - rectangle_begin.x, 1), -1); + int yDirection = MAX(MIN(end_tile.y - rectangle_begin.y, 1), -1); + end_tile = rectangle_begin + Point2i(xDirection * size, yDirection * size); + } + + _select(rectangle_begin, end_tile); if (tool == TOOL_RECTANGLE_ERASE) { if (paint_undo.size()) { @@ -1379,6 +1471,20 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { _update_button_tool(); return true; } + if (ED_IS_SHORTCUT("tile_map_editor/line_fill", p_event)) { + tool = TOOL_LINE_PAINT; + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } + if (ED_IS_SHORTCUT("tile_map_editor/rectangle_fill", p_event)) { + tool = TOOL_RECTANGLE_PAINT; + CanvasItemEditor::get_singleton()->update_viewport(); + + _update_button_tool(); + return true; + } if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) { tool = TOOL_BUCKET; CanvasItemEditor::get_singleton()->update_viewport(); @@ -1637,6 +1743,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } if (tool == TOOL_LINE_PAINT) { + if (!mouse_down) { + return; + } + if (paint_undo.empty()) { return; } @@ -1652,6 +1762,10 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { } } else if (tool == TOOL_RECTANGLE_PAINT) { + if (!mouse_down) { + return; + } + Vector<int> ids = get_selected_tiles(); if (ids.size() == 1 && ids[0] == TileMap::INVALID_CELL) { @@ -1865,6 +1979,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { tool = TOOL_NONE; selection_active = false; mouse_over = false; + mouse_down = false; flip_h = false; flip_v = false; @@ -1962,11 +2077,27 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { paint_button = memnew(Button); paint_button->set_flat(true); paint_button->set_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P)); - paint_button->set_tooltip(TTR("Shift+LMB: Line Draw\nShift+Ctrl+LMB: Rectangle Paint")); + paint_button->set_tooltip(TTR("RMB: Erase")); paint_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_NONE)); paint_button->set_toggle_mode(true); toolbar->add_child(paint_button); + line_button = memnew(Button); + line_button->set_flat(true); + line_button->set_shortcut(ED_SHORTCUT("tile_map_editor/line_fill", TTR("Line Fill"), KEY_L)); + line_button->set_tooltip(TTR("RMB: Erase")); + line_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_LINE_PAINT)); + line_button->set_toggle_mode(true); + toolbar->add_child(line_button); + + rectangle_button = memnew(Button); + rectangle_button->set_flat(true); + rectangle_button->set_shortcut(ED_SHORTCUT("tile_map_editor/rectangle_fill", TTR("Rectangle Fill"), KEY_O)); + rectangle_button->set_tooltip(TTR("Shift+LMB: Keep 1:1 proporsions\nRMB: Erase")); + rectangle_button->connect("pressed", callable_mp(this, &TileMapEditor::_button_tool_select), make_binds(TOOL_RECTANGLE_PAINT)); + rectangle_button->set_toggle_mode(true); + toolbar->add_child(rectangle_button); + bucket_fill_button = memnew(Button); bucket_fill_button->set_flat(true); bucket_fill_button->set_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_B)); diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h index 1d2ecdb61f..135a9bd5a5 100644 --- a/editor/plugins/tile_map_editor_plugin.h +++ b/editor/plugins/tile_map_editor_plugin.h @@ -88,6 +88,8 @@ class TileMapEditor : public VBoxContainer { MenuButton *options; Button *paint_button; + Button *line_button; + Button *rectangle_button; Button *bucket_fill_button; Button *picker_button; Button *select_button; @@ -106,6 +108,7 @@ class TileMapEditor : public VBoxContainer { bool selection_active; bool mouse_over; + bool mouse_down; bool flip_h; bool flip_v; diff --git a/editor/pot_generator.cpp b/editor/pot_generator.cpp new file mode 100644 index 0000000000..f9b8722aad --- /dev/null +++ b/editor/pot_generator.cpp @@ -0,0 +1,166 @@ +/*************************************************************************/ +/* pot_generator.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "pot_generator.h" + +#include "core/error_macros.h" +#include "core/os/file_access.h" +#include "core/project_settings.h" +#include "editor_translation_parser.h" +#include "plugins/packed_scene_translation_parser_plugin.h" + +POTGenerator *POTGenerator::singleton = nullptr; + +//#define DEBUG_POT + +#ifdef DEBUG_POT +void _print_all_translation_strings(const OrderedHashMap<String, Set<String>> &p_all_translation_strings) { + for (auto E_pair = p_all_translation_strings.front(); E_pair; E_pair = E_pair.next()) { + String msg = static_cast<String>(E_pair.key()) + " : "; + for (Set<String>::Element *E = E_pair.value().front(); E; E = E->next()) { + msg += E->get() + " "; + } + print_line(msg); + } +} +#endif + +void POTGenerator::generate_pot(const String &p_file) { + if (!ProjectSettings::get_singleton()->has_setting("locale/translations_pot_files")) { + WARN_PRINT("No files selected for POT generation."); + return; + } + + // Clear all_translation_strings of the previous round. + all_translation_strings.clear(); + + Vector<String> files = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + + // Collect all translatable strings according to files order in "POT Generation" setting. + for (int i = 0; i < files.size(); i++) { + Vector<String> translation_strings; + String file_path = files[i]; + String file_extension = file_path.get_extension(); + + if (EditorTranslationParser::get_singleton()->can_parse(file_extension)) { + EditorTranslationParser::get_singleton()->get_parser(file_extension)->parse_file(file_path, &translation_strings); + } else { + ERR_PRINT("Unrecognized file extension " + file_extension + " in generate_pot()"); + return; + } + + // Store translation strings parsed in this iteration along with their corresponding source file - to write into POT later on. + for (int j = 0; j < translation_strings.size(); j++) { + all_translation_strings[translation_strings[j]].insert(file_path); + } + } + +#ifdef DEBUG_POT + _print_all_translation_strings(all_translation_strings); +#endif + + _write_to_pot(p_file); +} + +void POTGenerator::_write_to_pot(const String &p_file) { + Error err; + FileAccess *file = FileAccess::open(p_file, FileAccess::WRITE, &err); + if (err != OK) { + ERR_PRINT("Failed to open " + p_file); + return; + } + + String project_name = ProjectSettings::get_singleton()->get("application/config/name"); + Vector<String> files = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + String extracted_files = ""; + for (int i = 0; i < files.size(); i++) { + extracted_files += "# " + files[i] + "\n"; + } + const String header = + "# LANGUAGE translation for " + project_name + " for the following files:\n" + extracted_files + + "#\n" + "#\n" + "# FIRST AUTHOR < EMAIL @ADDRESS>, YEAR.\n" + "#\n" + "#, fuzzy\n" + "msgid \"\"\n" + "msgstr \"\"\n" + "\"Project-Id-Version: " + + project_name + "\\n\"\n" + "\"Content-Type: text/plain; charset=UTF-8\\n\"\n" + "\"Content-Transfer-Encoding: 8-bit\\n\"\n\n"; + + file->store_string(header); + + for (OrderedHashMap<String, Set<String>>::Element E_pair = all_translation_strings.front(); E_pair; E_pair = E_pair.next()) { + String msg = E_pair.key(); + + // Write file locations. + for (Set<String>::Element *E = E_pair.value().front(); E; E = E->next()) { + file->store_line("#: " + E->get().trim_prefix("res://")); + } + + // Split \\n and \n. + Vector<String> temp = msg.split("\\n"); + Vector<String> msg_lines; + for (int i = 0; i < temp.size(); i++) { + msg_lines.append_array(temp[i].split("\n")); + if (i < temp.size() - 1) { + // Add \n. + msg_lines.set(msg_lines.size() - 1, msg_lines[msg_lines.size() - 1] + "\\n"); + } + } + + // Write msgid. + file->store_string("msgid "); + for (int i = 0; i < msg_lines.size(); i++) { + file->store_line("\"" + msg_lines[i] + "\""); + } + + file->store_line("msgstr \"\"\n"); + } + + file->close(); +} + +POTGenerator *POTGenerator::get_singleton() { + if (!singleton) { + singleton = memnew(POTGenerator); + } + return singleton; +} + +POTGenerator::POTGenerator() { +} + +POTGenerator::~POTGenerator() { + memdelete(singleton); + singleton = nullptr; +} diff --git a/editor/pane_drag.h b/editor/pot_generator.h index 81aff4b2a8..abe1a21d41 100644 --- a/editor/pane_drag.h +++ b/editor/pot_generator.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pane_drag.h */ +/* pot_generator.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,25 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PANE_DRAG_H -#define PANE_DRAG_H +#ifndef POT_GENERATOR_H +#define POT_GENERATOR_H -#include "scene/gui/control.h" +#include "core/ordered_hash_map.h" +#include "core/set.h" -class PaneDrag : public Control { - GDCLASS(PaneDrag, Control); +class POTGenerator { + static POTGenerator *singleton; + // Stores all translatable strings and the source files containing them. + OrderedHashMap<String, Set<String>> all_translation_strings; - bool mouse_over; - -protected: - void _gui_input(const Ref<InputEvent> &p_input); - void _notification(int p_what); - virtual Size2 get_minimum_size() const; - static void _bind_methods(); + void _write_to_pot(const String &p_file); public: - PaneDrag(); + static POTGenerator *get_singleton(); + void generate_pot(const String &p_file); + + POTGenerator(); + ~POTGenerator(); }; -#endif // PANE_DRAG_H +#endif // POT_GENERATOR_H diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index a800f9e8eb..325d7c5ce6 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -294,7 +294,7 @@ private: // If the project name is empty or default, infer the project name from the selected folder name if (project_name->get_text() == "" || project_name->get_text() == TTR("New Game Project")) { sp = sp.replace("\\", "/"); - int lidx = sp.find_last("/"); + int lidx = sp.rfind("/"); if (lidx != -1) { sp = sp.substr(lidx + 1, sp.length()).capitalize(); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index a8029e1e2b..f84845179b 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -38,6 +38,8 @@ #include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" +#include "editor/editor_translation_parser.h" +#include "editor/pot_generator.h" #include "scene/gui/margin_container.h" #include "scene/gui/tab_container.h" @@ -120,6 +122,7 @@ void ProjectSettingsEditor::_notification(int p_what) { action_add_error->add_theme_color_override("font_color", input_editor->get_theme_color("error_color", "Editor")); translation_list->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_translation_delete)); + translation_pot_list->connect("button_pressed", callable_mp(this, &ProjectSettingsEditor::_translation_pot_delete)); _update_actions(); popup_add->add_icon_item(input_editor->get_theme_icon("Keyboard", "EditorIcons"), TTR("Key"), INPUT_KEY); popup_add->add_icon_item(input_editor->get_theme_icon("KeyboardPhysical", "EditorIcons"), TTR("Physical Key"), INPUT_KEY_PHYSICAL); @@ -140,6 +143,9 @@ void ProjectSettingsEditor::_notification(int p_what) { translation_res_option_file_open->add_filter("*." + E->get()); } + _update_translation_pot_file_extensions(); + translation_pot_generate->add_filter("*.pot"); + restart_close_button->set_icon(input_editor->get_theme_icon("Close", "EditorIcons")); restart_container->add_theme_style_override("panel", input_editor->get_theme_stylebox("bg", "Tree")); restart_icon->set_texture(input_editor->get_theme_icon("StatusWarning", "EditorIcons")); @@ -865,6 +871,8 @@ void ProjectSettingsEditor::popup_project_settings() { _update_translations(); autoload_settings->update_autoload(); plugin_settings->update_plugins(); + // New translation parser plugin might extend possible file extensions in POT generation. + _update_translation_pot_file_extensions(); set_process_unhandled_input(true); } @@ -1519,8 +1527,71 @@ void ProjectSettingsEditor::_translation_filter_mode_changed(int p_mode) { undo_redo->commit_action(); } +void ProjectSettingsEditor::_translation_pot_add(const String &p_path) { + PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + + for (int i = 0; i < pot_translations.size(); i++) { + if (pot_translations[i] == p_path) { + return; //exists + } + } + + pot_translations.push_back(p_path); + undo_redo->create_action(TTR("Add files for POT generation")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", pot_translations); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", ProjectSettings::get_singleton()->get("locale/translations_pot_files")); + undo_redo->add_do_method(this, "_update_translations"); + undo_redo->add_undo_method(this, "_update_translations"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); +} + +void ProjectSettingsEditor::_translation_pot_delete(Object *p_item, int p_column, int p_button) { + TreeItem *ti = Object::cast_to<TreeItem>(p_item); + ERR_FAIL_COND(!ti); + + int idx = ti->get_metadata(0); + + PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + + ERR_FAIL_INDEX(idx, pot_translations.size()); + + pot_translations.remove(idx); + + undo_redo->create_action(TTR("Remove file from POT generation")); + undo_redo->add_do_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", pot_translations); + undo_redo->add_undo_property(ProjectSettings::get_singleton(), "locale/translations_pot_files", ProjectSettings::get_singleton()->get("locale/translations_pot_files")); + undo_redo->add_do_method(this, "_update_translations"); + undo_redo->add_undo_method(this, "_update_translations"); + undo_redo->add_do_method(this, "_settings_changed"); + undo_redo->add_undo_method(this, "_settings_changed"); + undo_redo->commit_action(); +} + +void ProjectSettingsEditor::_translation_pot_file_open() { + translation_pot_file_open->popup_centered_ratio(); +} + +void ProjectSettingsEditor::_translation_pot_generate_open() { + translation_pot_generate->popup_centered_ratio(); +} + +void ProjectSettingsEditor::_translation_pot_generate(const String &p_file) { + POTGenerator::get_singleton()->generate_pot(p_file); +} + +void ProjectSettingsEditor::_update_translation_pot_file_extensions() { + translation_pot_file_open->clear_filters(); + List<String> translation_parse_file_extensions; + EditorTranslationParser::get_singleton()->get_recognized_extensions(&translation_parse_file_extensions); + for (List<String>::Element *E = translation_parse_file_extensions.front(); E; E = E->next()) { + translation_pot_file_open->add_filter("*." + E->get()); + } +} + void ProjectSettingsEditor::_update_translations() { - //update translations + // Update translations. if (updating_translations) { return; @@ -1601,7 +1672,7 @@ void ProjectSettingsEditor::_update_translations() { } } - //update translation remaps + // Update translation remaps. String remap_selected; if (translation_remap->get_selected()) { @@ -1666,7 +1737,7 @@ void ProjectSettingsEditor::_update_translations() { PackedStringArray selected = remaps[keys[i]]; for (int j = 0; j < selected.size(); j++) { String s2 = selected[j]; - int qp = s2.find_last(":"); + int qp = s2.rfind(":"); String path = s2.substr(0, qp); String locale = s2.substr(qp + 1, s2.length()); @@ -1696,6 +1767,23 @@ void ProjectSettingsEditor::_update_translations() { } } + // Update translation POT files. + + translation_pot_list->clear(); + root = translation_pot_list->create_item(nullptr); + translation_pot_list->set_hide_root(true); + if (ProjectSettings::get_singleton()->has_setting("locale/translations_pot_files")) { + PackedStringArray pot_translations = ProjectSettings::get_singleton()->get("locale/translations_pot_files"); + for (int i = 0; i < pot_translations.size(); i++) { + TreeItem *t = translation_pot_list->create_item(root); + t->set_editable(0, false); + t->set_text(0, pot_translations[i].replace_first("res://", "")); + t->set_tooltip(0, pot_translations[i]); + t->set_metadata(0, i); + t->add_button(0, input_editor->get_theme_icon("Remove", "EditorIcons"), 0, false, TTR("Remove")); + } + } + updating_translations = false; } @@ -2108,6 +2196,38 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { translation_filter->connect("item_edited", callable_mp(this, &ProjectSettingsEditor::_translation_filter_option_changed)); } + { + VBoxContainer *tvb = memnew(VBoxContainer); + translations->add_child(tvb); + tvb->set_name(TTR("POT Generation")); + HBoxContainer *thb = memnew(HBoxContainer); + tvb->add_child(thb); + thb->add_child(memnew(Label(TTR("Files with translation strings:")))); + thb->add_spacer(); + Button *addtr = memnew(Button(TTR("Add..."))); + addtr->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_translation_pot_file_open)); + thb->add_child(addtr); + Button *generate = memnew(Button(TTR("Generate POT"))); + generate->connect("pressed", callable_mp(this, &ProjectSettingsEditor::_translation_pot_generate_open)); + thb->add_child(generate); + VBoxContainer *tmc = memnew(VBoxContainer); + tvb->add_child(tmc); + tmc->set_v_size_flags(Control::SIZE_EXPAND_FILL); + translation_pot_list = memnew(Tree); + translation_pot_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + tmc->add_child(translation_pot_list); + + translation_pot_generate = memnew(EditorFileDialog); + add_child(translation_pot_generate); + translation_pot_generate->set_file_mode(EditorFileDialog::FILE_MODE_SAVE_FILE); + translation_pot_generate->connect("file_selected", callable_mp(this, &ProjectSettingsEditor::_translation_pot_generate)); + + translation_pot_file_open = memnew(EditorFileDialog); + add_child(translation_pot_file_open); + translation_pot_file_open->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + translation_pot_file_open->connect("file_selected", callable_mp(this, &ProjectSettingsEditor::_translation_pot_add)); + } + autoload_settings = memnew(EditorAutoloadSettings); autoload_settings->set_name(TTR("AutoLoad")); tab_container->add_child(autoload_settings); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 728f31efa8..cf47b1df4a 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -110,6 +110,10 @@ class ProjectSettingsEditor : public AcceptDialog { Vector<TreeItem *> translation_filter_treeitems; Vector<int> translation_locales_idxs_remap; + Tree *translation_pot_list; + EditorFileDialog *translation_pot_file_open; + EditorFileDialog *translation_pot_generate; + EditorAutoloadSettings *autoload_settings; EditorPluginSettings *plugin_settings; @@ -159,6 +163,13 @@ class ProjectSettingsEditor : public AcceptDialog { void _translation_filter_option_changed(); void _translation_filter_mode_changed(int p_mode); + void _translation_pot_add(const String &p_path); + void _translation_pot_delete(Object *p_item, int p_column, int p_button); + void _translation_pot_file_open(); + void _translation_pot_generate_open(); + void _translation_pot_generate(const String &p_file); + void _update_translation_pot_file_extensions(); + void _toggle_search_bar(bool p_pressed); Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 49b9ca167b..f4838d336f 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -597,7 +597,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_METHOD_OF_INSTANCE) { MAKE_PROPSELECT - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { property_select->select_method_from_instance(instance, v); } @@ -607,7 +607,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_METHOD_OF_SCRIPT) { MAKE_PROPSELECT - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { property_select->select_method_from_script(Object::cast_to<Script>(obj), v); } @@ -646,7 +646,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_PROPERTY_OF_INSTANCE) { MAKE_PROPSELECT - Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *instance = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (instance) { property_select->select_property_from_instance(instance, v); } @@ -657,7 +657,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_PROPERTY_OF_SCRIPT) { MAKE_PROPSELECT - Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int64())); + Object *obj = ObjectDB::get_instance(ObjectID(hint_text.to_int())); if (Object::cast_to<Script>(obj)) { property_select->select_property_from_script(Object::cast_to<Script>(obj), v); } diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp index bcef29dfa6..4af6fb2053 100644 --- a/editor/quick_open.cpp +++ b/editor/quick_open.cpp @@ -32,21 +32,18 @@ #include "core/os/keyboard.h" -void EditorQuickOpen::popup_dialog(const StringName &p_base, bool p_enable_multi, bool p_add_dirs, bool p_dontclear) { - add_directories = p_add_dirs; - popup_centered_ratio(0.6); +void EditorQuickOpen::popup_dialog(const StringName &p_base, bool p_enable_multi, bool p_dontclear) { + base_type = p_base; + search_options->set_select_mode(p_enable_multi ? Tree::SELECT_MULTI : Tree::SELECT_SINGLE); + popup_centered_ratio(0.4); + if (p_dontclear) { search_box->select_all(); } else { search_box->clear(); } - if (p_enable_multi) { - search_options->set_select_mode(Tree::SELECT_MULTI); - } else { - search_options->set_select_mode(Tree::SELECT_SINGLE); - } + search_box->grab_focus(); - base_type = p_base; _update_search(); } @@ -65,7 +62,6 @@ Vector<String> EditorQuickOpen::get_selected_files() const { TreeItem *item = search_options->get_next_selected(search_options->get_root()); while (item) { files.push_back("res://" + item->get_text(0)); - item = search_options->get_next_selected(item); } @@ -93,7 +89,6 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { } TreeItem *current = search_options->get_selected(); - TreeItem *item = search_options->get_next_selected(root); while (item) { item->deselect(0); @@ -101,88 +96,55 @@ void EditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { } current->select(0); - + current->set_as_cursor(0); } break; } } } -float EditorQuickOpen::_path_cmp(String search, String path) const { - // Exact match. - if (search == path) { - return 1.2f; +float EditorQuickOpen::_score_path(String search, String path) const { + // Positive bias for matches close to the _beginning of the file name_. + String file = path.get_file(); + int pos = file.findn(search); + if (pos != -1) { + return 1.0f - 0.1f * (float(pos) / file.length()); } - // Substring match, with positive bias for matches close to the end of the path. - int pos = path.rfindn(search); + // Positive bias for matches close to the _end of the path_. + String base = path.get_base_dir(); + pos = base.rfindn(search); if (pos != -1) { - return 1.1f + 0.09 / (path.length() - pos + 1); + return 0.9f - 0.1f * (float(base.length() - pos) / base.length()); } - // Similarity. - return path.to_lower().similarity(search.to_lower()); + // Results that contain all characters but not the string. + return path.similarity(search) * 0.8f; } void EditorQuickOpen::_parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<String, Ref<Texture2D>>> &list) { - if (!add_directories) { - for (int i = 0; i < efsd->get_subdir_count(); i++) { - _parse_fs(efsd->get_subdir(i), list); - } + for (int i = 0; i < efsd->get_subdir_count(); i++) { + _parse_fs(efsd->get_subdir(i), list); } - String search_text = search_box->get_text(); - - if (add_directories) { - String path = efsd->get_path(); - if (!path.ends_with("/")) { - path += "/"; - } - if (path != "res://") { - path = path.substr(6, path.length()); - if (search_text.is_subsequence_ofi(path)) { - Pair<String, Ref<Texture2D>> pair; - pair.first = path; - pair.second = search_options->get_theme_icon("folder", "FileDialog"); - - if (search_text != String() && list.size() > 0) { - float this_sim = _path_cmp(search_text, path); - float other_sim = _path_cmp(list[0].first, path); - int pos = 1; - - while (pos < list.size() && this_sim <= other_sim) { - other_sim = _path_cmp(list[pos++].first, path); - } + for (int i = 0; i < efsd->get_file_count(); i++) { + StringName file_type = efsd->get_file_type(i); - pos = this_sim >= other_sim ? pos - 1 : pos; - list.insert(pos, pair); + if (ClassDB::is_parent_class(file_type, base_type)) { + String file = efsd->get_file_path(i); + file = file.substr(6, file.length()); - } else { - list.push_back(pair); - } + if (search_box->get_text().is_subsequence_ofi(file)) { + Pair<String, Ref<Texture2D>> pair; + pair.first = file; + pair.second = search_options->get_theme_icon(search_options->has_theme_icon(file_type, ei) ? file_type : ot, ei); + list.push_back(pair); } } } - for (int i = 0; i < efsd->get_file_count(); i++) { - String file = efsd->get_file_path(i); - file = file.substr(6, file.length()); - - if (ClassDB::is_parent_class(efsd->get_file_type(i), base_type) && (search_text.is_subsequence_ofi(file))) { - Pair<String, Ref<Texture2D>> pair; - pair.first = file; - pair.second = search_options->get_theme_icon((search_options->has_theme_icon(efsd->get_file_type(i), ei) ? efsd->get_file_type(i) : ot), ei); - list.push_back(pair); - } - } - - if (add_directories) { - for (int i = 0; i < efsd->get_subdir_count(); i++) { - _parse_fs(efsd->get_subdir(i), list); - } - } } Vector<Pair<String, Ref<Texture2D>>> EditorQuickOpen::_sort_fs(Vector<Pair<String, Ref<Texture2D>>> &list) { - String search_text = search_box->get_text(); + String search_text = search_box->get_text().to_lower(); Vector<Pair<String, Ref<Texture2D>>> sorted_list; if (search_text == String() || list.size() == 0) { @@ -192,7 +154,7 @@ Vector<Pair<String, Ref<Texture2D>>> EditorQuickOpen::_sort_fs(Vector<Pair<Strin Vector<float> scores; scores.resize(list.size()); for (int i = 0; i < list.size(); i++) { - scores.write[i] = _path_cmp(search_text, list[i].first); + scores.write[i] = _score_path(search_text, list[i].first.to_lower()); } while (list.size() > 0) { @@ -230,19 +192,17 @@ void EditorQuickOpen::_update_search() { ti->set_icon(0, list[i].second); } - if (root->get_children()) { - TreeItem *ti = root->get_children(); - - ti->select(0); - ti->set_as_cursor(0); + TreeItem *result = root->get_children(); + if (result) { + result->select(0); + result->set_as_cursor(0); } - get_ok()->set_disabled(root->get_children() == nullptr); + get_ok()->set_disabled(!result); } void EditorQuickOpen::_confirmed() { - TreeItem *ti = search_options->get_selected(); - if (!ti) { + if (!search_options->get_selected()) { return; } emit_signal("quick_open"); @@ -250,7 +210,7 @@ void EditorQuickOpen::_confirmed() { } void EditorQuickOpen::_theme_changed() { - search_box->set_right_icon(search_options->get_theme_icon("Search", "EditorIcons")); + search_box->set_right_icon(search_options->get_theme_icon("Search", ei)); } void EditorQuickOpen::_notification(int p_what) { @@ -277,23 +237,24 @@ void EditorQuickOpen::_bind_methods() { EditorQuickOpen::EditorQuickOpen() { VBoxContainer *vbc = memnew(VBoxContainer); vbc->connect("theme_changed", callable_mp(this, &EditorQuickOpen::_theme_changed)); - add_child(vbc); + search_box = memnew(LineEdit); - vbc->add_margin_child(TTR("Search:"), search_box); search_box->connect("text_changed", callable_mp(this, &EditorQuickOpen::_text_changed)); search_box->connect("gui_input", callable_mp(this, &EditorQuickOpen::_sbox_input)); + vbc->add_margin_child(TTR("Search:"), search_box); + search_options = memnew(Tree); - vbc->add_margin_child(TTR("Matches:"), search_options, true); - get_ok()->set_text(TTR("Open")); - get_ok()->set_disabled(true); - register_text_enter(search_box); - set_hide_on_ok(false); search_options->connect("item_activated", callable_mp(this, &EditorQuickOpen::_confirmed)); search_options->set_hide_root(true); search_options->set_hide_folding(true); search_options->add_theme_constant_override("draw_guides", 1); + vbc->add_margin_child(TTR("Matches:"), search_options, true); + + get_ok()->set_text(TTR("Open")); + register_text_enter(search_box); + set_hide_on_ok(false); + ei = "EditorIcons"; ot = "Object"; - add_directories = false; } diff --git a/editor/quick_open.h b/editor/quick_open.h index e446ed6823..5bcdfc7bf2 100644 --- a/editor/quick_open.h +++ b/editor/quick_open.h @@ -35,22 +35,23 @@ #include "editor_file_system.h" #include "scene/gui/dialogs.h" #include "scene/gui/tree.h" + class EditorQuickOpen : public ConfirmationDialog { GDCLASS(EditorQuickOpen, ConfirmationDialog); LineEdit *search_box; Tree *search_options; + StringName base_type; StringName ei; StringName ot; - bool add_directories; void _update_search(); void _sbox_input(const Ref<InputEvent> &p_ie); void _parse_fs(EditorFileSystemDirectory *efsd, Vector<Pair<String, Ref<Texture2D>>> &list); Vector<Pair<String, Ref<Texture2D>>> _sort_fs(Vector<Pair<String, Ref<Texture2D>>> &list); - float _path_cmp(String search, String path) const; + float _score_path(String search, String path) const; void _confirmed(); void _text_changed(const String &p_newtext); @@ -67,7 +68,7 @@ public: String get_selected() const; Vector<String> get_selected_files() const; - void popup_dialog(const StringName &p_base, bool p_enable_multi = false, bool p_add_dirs = false, bool p_dontclear = false); + void popup_dialog(const StringName &p_base, bool p_enable_multi = false, bool p_dontclear = false); EditorQuickOpen(); }; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index dd42ed9760..41b8baeb2f 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -350,17 +350,26 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (!profile_allow_editing) { break; } - String preferred = ""; - Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene(); + // Prefer nodes that inherit from the current scene root. + Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene(); if (current_edited_scene_root) { - if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node2D")) { - preferred = "Node2D"; - } else if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node3D")) { - preferred = "Node3D"; + String root_class = current_edited_scene_root->get_class_name(); + static Vector<String> preferred_types; + if (preferred_types.empty()) { + preferred_types.push_back("Control"); + preferred_types.push_back("Node2D"); + preferred_types.push_back("Node3D"); + } + + for (int i = 0; i < preferred_types.size(); i++) { + if (ClassDB::is_parent_class(root_class, preferred_types[i])) { + create_dialog->set_preferred_search_result_type(preferred_types[i]); + break; + } } } - create_dialog->set_preferred_search_result_type(preferred); + create_dialog->popup_create(true); } break; case TOOL_INSTANCE: { @@ -736,17 +745,28 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { _delete_confirm(); } else { - if (remove_list.size() >= 2) { - delete_dialog->set_text(vformat(TTR("Delete %d nodes?"), remove_list.size())); - } else if (remove_list.size() == 1 && remove_list[0] == editor_data->get_edited_scene_root()) { - delete_dialog->set_text(vformat(TTR("Delete the root node \"%s\"?"), remove_list[0]->get_name())); - } else if (remove_list.size() == 1 && remove_list[0]->get_filename() == "" && remove_list[0]->get_child_count() >= 1) { - // Display this message only for non-instanced scenes - delete_dialog->set_text(vformat(TTR("Delete node \"%s\" and its children?"), remove_list[0]->get_name())); + String msg; + if (remove_list.size() > 1) { + bool any_children = false; + for (int i = 0; !any_children && i < remove_list.size(); i++) { + any_children = remove_list[i]->get_child_count() > 0; + } + + msg = vformat(any_children ? TTR("Delete %d nodes and any children?") : TTR("Delete %d nodes?"), remove_list.size()); } else { - delete_dialog->set_text(vformat(TTR("Delete node \"%s\"?"), remove_list[0]->get_name())); + Node *node = remove_list[0]; + if (node == editor_data->get_edited_scene_root()) { + msg = vformat(TTR("Delete the root node \"%s\"?"), node->get_name()); + } else if (node->get_filename() == "" && node->get_child_count() > 0) { + // Display this message only for non-instanced scenes + msg = vformat(TTR("Delete node \"%s\" and its children?"), node->get_name()); + } else { + msg = vformat(TTR("Delete node \"%s\"?"), node->get_name()); + } } + delete_dialog->set_text(msg); + // Resize the dialog to its minimum size. // This prevents the dialog from being too wide after displaying // a deletion confirmation for a node with a long name. @@ -2383,7 +2403,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } menu->set_size(Size2(1, 1)); - menu->set_position(p_menu_pos); + menu->set_position(get_screen_position() + p_menu_pos); menu->popup(); return; } diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 1b818036e1..f30e57579f 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -902,6 +902,10 @@ Variant SceneTreeEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from return Variant(); //not editable tree } + if (tree->get_button_id_at_position(p_point) != -1) { + return Variant(); //dragging from button + } + Vector<Node *> selected; Vector<Ref<Texture2D>> icons; TreeItem *next = tree->get_next_selected(nullptr); @@ -1072,7 +1076,7 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, } void SceneTreeEditor::_rmb_select(const Vector2 &p_pos) { - emit_signal("rmb_pressed", tree->get_global_transform().xform(p_pos)); + emit_signal("rmb_pressed", tree->get_screen_transform().xform(p_pos)); } void SceneTreeEditor::_warning_changed(Node *p_for_node) { diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index ae5229b628..40e0582046 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -78,7 +78,7 @@ void ScriptCreateDialog::_notification(int p_what) { void ScriptCreateDialog::_path_hbox_sorted() { if (is_visible()) { - int filename_start_pos = initial_bp.find_last("/") + 1; + int filename_start_pos = initial_bp.rfind("/") + 1; int filename_end_pos = initial_bp.length(); if (!is_built_in) { @@ -553,7 +553,7 @@ void ScriptCreateDialog::_file_selected(const String &p_file) { _path_changed(p); String filename = p.get_file().get_basename(); - int select_start = p.find_last(filename); + int select_start = p.rfind(filename); file_path->select(select_start, select_start + filename.length()); file_path->set_cursor_position(select_start + filename.length()); file_path->grab_focus(); diff --git a/main/main.cpp b/main/main.cpp index 00760b39b0..608b4a7c4d 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -780,7 +780,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (I->get().ends_with("project.godot")) { String path; String file = I->get(); - int sep = MAX(file.find_last("/"), file.find_last("\\")); + int sep = MAX(file.rfind("/"), file.rfind("\\")); if (sep == -1) { path = "."; } else { @@ -856,7 +856,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } } else if (I->get() == "--allow_focus_steal_pid") { // not exposed to user if (I->next()) { - allow_focus_steal_pid = I->next()->get().to_int64(); + allow_focus_steal_pid = I->next()->get().to_int(); N = I->next()->next(); } else { OS::get_singleton()->print("Missing editor PID argument, aborting.\n"); @@ -1620,7 +1620,7 @@ bool Main::start() { { DirAccessRef da = DirAccess::open(doc_tool); - ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a base Godot build directory."); + ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path."); } #ifndef MODULE_MONO_ENABLED @@ -1895,10 +1895,10 @@ bool Main::start() { Size2i stretch_size = Size2(GLOBAL_DEF("display/window/size/width", 0), GLOBAL_DEF("display/window/size/height", 0)); Window::ContentScaleMode cs_sm = Window::CONTENT_SCALE_MODE_DISABLED; - if (stretch_mode == "objects") { - cs_sm = Window::CONTENT_SCALE_MODE_OBJECTS; - } else if (stretch_mode == "pixels") { - cs_sm = Window::CONTENT_SCALE_MODE_PIXELS; + if (stretch_mode == "canvas_items") { + cs_sm = Window::CONTENT_SCALE_MODE_CANVAS_ITEMS; + } else if (stretch_mode == "viewport") { + cs_sm = Window::CONTENT_SCALE_MODE_VIEWPORT; } Window::ContentScaleAspect cs_aspect = Window::CONTENT_SCALE_ASPECT_IGNORE; @@ -1954,7 +1954,7 @@ bool Main::start() { } else { GLOBAL_DEF("display/window/stretch/mode", "disabled"); - ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", PropertyInfo(Variant::STRING, "display/window/stretch/mode", PROPERTY_HINT_ENUM, "disabled,2d,viewport")); + ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/mode", PropertyInfo(Variant::STRING, "display/window/stretch/mode", PROPERTY_HINT_ENUM, "disabled,canvas_items,viewport")); GLOBAL_DEF("display/window/stretch/aspect", "ignore"); ProjectSettings::get_singleton()->set_custom_property_info("display/window/stretch/aspect", PropertyInfo(Variant::STRING, "display/window/stretch/aspect", PROPERTY_HINT_ENUM, "ignore,keep,keep_width,keep_height,expand")); GLOBAL_DEF("display/window/stretch/shrink", 1.0); @@ -1992,7 +1992,7 @@ bool Main::start() { local_game_path = "res://" + local_game_path; } else { - int sep = local_game_path.find_last("/"); + int sep = local_game_path.rfind("/"); if (sep == -1) { DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); @@ -2115,7 +2115,6 @@ bool Main::start() { */ uint64_t Main::last_ticks = 0; -uint64_t Main::target_ticks = 0; uint32_t Main::frames = 0; uint32_t Main::frame = 0; bool Main::force_redraw_requested = false; @@ -2266,38 +2265,7 @@ bool Main::iteration() { return exit; } - const uint32_t frame_delay = Engine::get_singleton()->get_frame_delay(); - if (frame_delay) { - // Add fixed frame delay to decrease CPU/GPU usage. This doesn't take - // the actual frame time into account. - // Due to the high fluctuation of the actual sleep duration, it's not recommended - // to use this as a FPS limiter. - OS::get_singleton()->delay_usec(frame_delay * 1000); - } - - // Add a dynamic frame delay to decrease CPU/GPU usage. This takes the - // previous frame time into account for a smoother result. - uint64_t dynamic_delay = 0; - if (OS::get_singleton()->is_in_low_processor_usage_mode() || !DisplayServer::get_singleton()->window_can_draw()) { - dynamic_delay = OS::get_singleton()->get_low_processor_usage_mode_sleep_usec(); - } - const int target_fps = Engine::get_singleton()->get_target_fps(); - if (target_fps > 0 && !Engine::get_singleton()->is_editor_hint()) { - // Override the low processor usage mode sleep delay if the target FPS is lower. - dynamic_delay = MAX(dynamic_delay, (uint64_t)(1000000 / target_fps)); - } - - if (dynamic_delay > 0) { - target_ticks += dynamic_delay; - uint64_t current_ticks = OS::get_singleton()->get_ticks_usec(); - - if (current_ticks < target_ticks) { - OS::get_singleton()->delay_usec(target_ticks - current_ticks); - } - - current_ticks = OS::get_singleton()->get_ticks_usec(); - target_ticks = MIN(MAX(target_ticks, current_ticks - dynamic_delay), current_ticks + dynamic_delay); - } + OS::get_singleton()->add_frame_delay(DisplayServer::get_singleton()->window_can_draw()); #ifdef TOOLS_ENABLED if (auto_build_solutions) { diff --git a/main/main.h b/main/main.h index ab6917a65c..308128735c 100644 --- a/main/main.h +++ b/main/main.h @@ -38,7 +38,6 @@ class Main { static void print_help(const char *p_binary); static uint64_t last_ticks; - static uint64_t target_ticks; static uint32_t frames; static uint32_t frame; static bool force_redraw_requested; diff --git a/main/performance.cpp b/main/performance.cpp index 7e6b9fca64..7234511aeb 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -43,6 +43,12 @@ Performance *Performance::singleton = nullptr; void Performance::_bind_methods() { ClassDB::bind_method(D_METHOD("get_monitor", "monitor"), &Performance::get_monitor); + ClassDB::bind_method(D_METHOD("add_custom_monitor", "id", "callable", "arguments"), &Performance::add_custom_monitor, DEFVAL(Array())); + ClassDB::bind_method(D_METHOD("remove_custom_monitor", "id"), &Performance::remove_custom_monitor); + ClassDB::bind_method(D_METHOD("has_custom_monitor", "id"), &Performance::has_custom_monitor); + ClassDB::bind_method(D_METHOD("get_custom_monitor", "id"), &Performance::get_custom_monitor); + ClassDB::bind_method(D_METHOD("get_monitor_modification_time"), &Performance::get_monitor_modification_time); + ClassDB::bind_method(D_METHOD("get_custom_monitor_names"), &Performance::get_custom_monitor_names); BIND_ENUM_CONSTANT(TIME_FPS); BIND_ENUM_CONSTANT(TIME_PROCESS); @@ -231,8 +237,78 @@ void Performance::set_physics_process_time(float p_pt) { _physics_process_time = p_pt; } +void Performance::add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args) { + ERR_FAIL_COND_MSG(has_custom_monitor(p_id), "Custom monitor with id '" + String(p_id) + "' already exists."); + _monitor_map.insert(p_id, MonitorCall(p_callable, p_args)); + _monitor_modification_time = OS::get_singleton()->get_ticks_usec(); +} + +void Performance::remove_custom_monitor(const StringName &p_id) { + ERR_FAIL_COND_MSG(!has_custom_monitor(p_id), "Custom monitor with id '" + String(p_id) + "' doesn't exists."); + _monitor_map.erase(p_id); + _monitor_modification_time = OS::get_singleton()->get_ticks_usec(); +} + +bool Performance::has_custom_monitor(const StringName &p_id) { + return _monitor_map.has(p_id); +} + +Variant Performance::get_custom_monitor(const StringName &p_id) { + ERR_FAIL_COND_V_MSG(!has_custom_monitor(p_id), Variant(), "Custom monitor with id '" + String(p_id) + "' doesn't exists."); + bool error; + String error_message; + Variant return_value = _monitor_map[p_id].call(error, error_message); + ERR_FAIL_COND_V_MSG(error, return_value, "Error calling from custom monitor '" + String(p_id) + "' to callable: " + error_message); + return return_value; +} + +Array Performance::get_custom_monitor_names() { + if (!_monitor_map.size()) { + return Array(); + } + Array return_array; + return_array.resize(_monitor_map.size()); + int index = 0; + for (OrderedHashMap<StringName, MonitorCall>::Element i = _monitor_map.front(); i; i = i.next()) { + return_array.set(index, i.key()); + index++; + } + return return_array; +} + +uint64_t Performance::get_monitor_modification_time() { + return _monitor_modification_time; +} + Performance::Performance() { _process_time = 0; _physics_process_time = 0; + _monitor_modification_time = 0; singleton = this; } + +Performance::MonitorCall::MonitorCall(Callable p_callable, Vector<Variant> p_arguments) { + _callable = p_callable; + _arguments = p_arguments; +} + +Performance::MonitorCall::MonitorCall() { +} + +Variant Performance::MonitorCall::call(bool &r_error, String &r_error_message) { + Vector<const Variant *> arguments_mem; + arguments_mem.resize(_arguments.size()); + for (int i = 0; i < _arguments.size(); i++) { + arguments_mem.write[i] = &_arguments[i]; + } + const Variant **args = (const Variant **)arguments_mem.ptr(); + int argc = _arguments.size(); + Variant return_value; + Callable::CallError error; + _callable.call(args, argc, return_value, error); + r_error = (error.error != Callable::CallError::CALL_OK); + if (r_error) { + r_error_message = Variant::get_callable_error_text(_callable, args, argc, error); + } + return return_value; +} diff --git a/main/performance.h b/main/performance.h index ddbe45fa00..5f88a24c0f 100644 --- a/main/performance.h +++ b/main/performance.h @@ -32,6 +32,7 @@ #define PERFORMANCE_H #include "core/object.h" +#include "core/ordered_hash_map.h" #define PERF_WARN_OFFLINE_FUNCTION #define PERF_WARN_PROCESS_SYNC @@ -47,6 +48,19 @@ class Performance : public Object { float _process_time; float _physics_process_time; + class MonitorCall { + Callable _callable; + Vector<Variant> _arguments; + + public: + MonitorCall(Callable p_callable, Vector<Variant> p_arguments); + MonitorCall(); + Variant call(bool &r_error, String &r_error_message); + }; + + OrderedHashMap<StringName, MonitorCall> _monitor_map; + uint64_t _monitor_modification_time; + public: enum Monitor { @@ -95,6 +109,14 @@ public: void set_process_time(float p_pt); void set_physics_process_time(float p_pt); + void add_custom_monitor(const StringName &p_id, const Callable &p_callable, const Vector<Variant> &p_args); + void remove_custom_monitor(const StringName &p_id); + bool has_custom_monitor(const StringName &p_id); + Variant get_custom_monitor(const StringName &p_id); + Array get_custom_monitor_names(); + + uint64_t get_monitor_modification_time(); + static Performance *get_singleton() { return singleton; } Performance(); diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp index 775c039282..5a14492be5 100644 --- a/main/tests/test_string.cpp +++ b/main/tests/test_string.cpp @@ -370,7 +370,7 @@ bool test_22() { static const int num[4] = { 1237461283, -22, 0, -1123412 }; for (int i = 0; i < 4; i++) { - OS::get_singleton()->print("\tString: \"%s\" as Int is %i\n", nums[i], String(nums[i]).to_int()); + OS::get_singleton()->print("\tString: \"%s\" as Int is %lli\n", nums[i], (long long)(String(nums[i]).to_int())); if (String(nums[i]).to_int() != num[i]) { return false; diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj index 2ae3564faf..8c92ae2a7c 100644 --- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj +++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj @@ -16,6 +16,20 @@ D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 90A13CD024AA68E500E8464F /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + $pbx_embeded_frameworks + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = "$binary/dylibs"; sourceTree = "<group>"; }; DEADBEEF1F582BE20003B888 /* $binary.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = godot; path = "$binary.a"; sourceTree = "<group>"; }; @@ -105,6 +119,7 @@ D0BCFE3018AEBDA2004A7AAE /* Sources */, D0BCFE3118AEBDA2004A7AAE /* Frameworks */, D0BCFE3218AEBDA2004A7AAE /* Resources */, + 90A13CD024AA68E500E8464F /* Embed Frameworks */, ); buildRules = ( ); @@ -230,7 +245,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1F1575721F582BE20003B888 /* dylibs in Resources */, D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */, D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */, D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */, @@ -284,7 +298,9 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug"; COPY_PHASE_STRIP = NO; ENABLE_BITCODE = NO; - "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary/**"; + "FRAMEWORK_SEARCH_PATHS[arch=*]" = ( + "$(PROJECT_DIR)/**", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -327,7 +343,9 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release"; COPY_PHASE_STRIP = YES; ENABLE_BITCODE = NO; - "FRAMEWORK_SEARCH_PATHS[arch=*]" = "$binary/**"; + "FRAMEWORK_SEARCH_PATHS[arch=*]" = ( + "$(PROJECT_DIR)/**", + ); ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -357,6 +375,10 @@ DEVELOPMENT_TEAM = $team_id; INFOPLIST_FILE = "$binary/$binary-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -383,6 +405,10 @@ DEVELOPMENT_TEAM = $team_id; INFOPLIST_FILE = "$binary/$binary-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist index add2f6c084..e0cad2e7d1 100644 --- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist +++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist @@ -26,6 +26,8 @@ <string>$signature</string> <key>CFBundleVersion</key> <string>$version</string> + <key>ITSAppUsesNonExemptEncryption</key> + <false /> <key>LSRequiresIPhoneOS</key> <true/> <key>LSSupportsOpeningDocumentsInPlace</key> diff --git a/misc/dist/osx_template.app/Contents/Info.plist b/misc/dist/osx_template.app/Contents/Info.plist index aaee42aa5f..aad24935d0 100755 --- a/misc/dist/osx_template.app/Contents/Info.plist +++ b/misc/dist/osx_template.app/Contents/Info.plist @@ -30,12 +30,18 @@ <string>$camera_usage_description</string> <key>NSHumanReadableCopyright</key> <string>$copyright</string> + <key>CFBundleSupportedPlatforms</key> + <array> + <string>MacOSX</string> + </array> + <key>NSPrincipalClass</key> + <string>NSApplication</string> <key>LSMinimumSystemVersion</key> - <string>10.12.0</string> + <string>10.12</string> <key>LSMinimumSystemVersionByArchitecture</key> <dict> <key>x86_64</key> - <string>10.12.0</string> + <string>10.12</string> </dict> <key>NSHighResolutionCapable</key> $highres diff --git a/misc/dist/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist index c519a232c4..fd62bc0ef5 100755 --- a/misc/dist/osx_tools.app/Contents/Info.plist +++ b/misc/dist/osx_tools.app/Contents/Info.plist @@ -29,15 +29,21 @@ <key>NSCameraUsageDescription</key> <string>Camera access is required to capture video.</string> <key>NSRequiresAquaSystemAppearance</key> - <false /> + <false/> <key>NSHumanReadableCopyright</key> <string>© 2007-2020 Juan Linietsky, Ariel Manzur & Godot Engine contributors</string> + <key>CFBundleSupportedPlatforms</key> + <array> + <string>MacOSX</string> + </array> + <key>NSPrincipalClass</key> + <string>NSApplication</string> <key>LSMinimumSystemVersion</key> - <string>10.12.0</string> + <string>10.12</string> <key>LSMinimumSystemVersionByArchitecture</key> <dict> <key>x86_64</key> - <string>10.12.0</string> + <string>10.12</string> </dict> <key>NSHighResolutionCapable</key> <true/> diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 55686543f3..f397c53344 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -707,11 +707,11 @@ void BulletPhysicsServer3D::body_add_central_force(RID p_body, const Vector3 &p_ body->apply_central_force(p_force); } -void BulletPhysicsServer3D::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { +void BulletPhysicsServer3D::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->apply_force(p_force, p_pos); + body->apply_force(p_force, p_position); } void BulletPhysicsServer3D::body_add_torque(RID p_body, const Vector3 &p_torque) { @@ -728,11 +728,11 @@ void BulletPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 body->apply_central_impulse(p_impulse); } -void BulletPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { +void BulletPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->apply_impulse(p_pos, p_impulse); + body->apply_impulse(p_impulse, p_position); } void BulletPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 558d1ce5f7..8e8b33a4b8 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -223,11 +223,11 @@ public: virtual Vector3 body_get_applied_torque(RID p_body) const; virtual void body_add_central_force(RID p_body, const Vector3 &p_force); - virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos); + virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()); virtual void body_add_torque(RID p_body, const Vector3 &p_torque); virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse); - virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse); + virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity); diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 9aac7ba9e4..6cfbe18a64 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -118,8 +118,8 @@ void BulletPhysicsDirectBodyState3D::add_central_force(const Vector3 &p_force) { body->apply_central_force(p_force); } -void BulletPhysicsDirectBodyState3D::add_force(const Vector3 &p_force, const Vector3 &p_pos) { - body->apply_force(p_force, p_pos); +void BulletPhysicsDirectBodyState3D::add_force(const Vector3 &p_force, const Vector3 &p_position) { + body->apply_force(p_force, p_position); } void BulletPhysicsDirectBodyState3D::add_torque(const Vector3 &p_torque) { @@ -130,8 +130,8 @@ void BulletPhysicsDirectBodyState3D::apply_central_impulse(const Vector3 &p_impu body->apply_central_impulse(p_impulse); } -void BulletPhysicsDirectBodyState3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - body->apply_impulse(p_pos, p_impulse); +void BulletPhysicsDirectBodyState3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { + body->apply_impulse(p_impulse, p_position); } void BulletPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impulse) { @@ -604,23 +604,23 @@ Variant RigidBodyBullet::get_state(PhysicsServer3D::BodyState p_state) const { } void RigidBodyBullet::apply_central_impulse(const Vector3 &p_impulse) { - btVector3 btImpu; - G_TO_B(p_impulse, btImpu); + btVector3 btImpulse; + G_TO_B(p_impulse, btImpulse); if (Vector3() != p_impulse) { btBody->activate(); } - btBody->applyCentralImpulse(btImpu); + btBody->applyCentralImpulse(btImpulse); } -void RigidBodyBullet::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - btVector3 btImpu; - btVector3 btPos; - G_TO_B(p_impulse, btImpu); - G_TO_B(p_pos, btPos); +void RigidBodyBullet::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { + btVector3 btImpulse; + btVector3 btPosition; + G_TO_B(p_impulse, btImpulse); + G_TO_B(p_position, btPosition); if (Vector3() != p_impulse) { btBody->activate(); } - btBody->applyImpulse(btImpu, btPos); + btBody->applyImpulse(btImpulse, btPosition); } void RigidBodyBullet::apply_torque_impulse(const Vector3 &p_impulse) { @@ -632,15 +632,15 @@ void RigidBodyBullet::apply_torque_impulse(const Vector3 &p_impulse) { btBody->applyTorqueImpulse(btImp); } -void RigidBodyBullet::apply_force(const Vector3 &p_force, const Vector3 &p_pos) { +void RigidBodyBullet::apply_force(const Vector3 &p_force, const Vector3 &p_position) { btVector3 btForce; - btVector3 btPos; + btVector3 btPosition; G_TO_B(p_force, btForce); - G_TO_B(p_pos, btPos); + G_TO_B(p_position, btPosition); if (Vector3() != p_force) { btBody->activate(); } - btBody->applyForce(btForce, btPos); + btBody->applyForce(btForce, btPosition); } void RigidBodyBullet::apply_central_force(const Vector3 &p_force) { diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index 6d159504b8..ddc9d2916a 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -111,10 +111,10 @@ public: virtual Transform get_transform() const; virtual void add_central_force(const Vector3 &p_force); - virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos); + virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()); virtual void add_torque(const Vector3 &p_torque); virtual void apply_central_impulse(const Vector3 &p_impulse); - virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); virtual void apply_torque_impulse(const Vector3 &p_impulse); virtual void set_sleep_state(bool p_sleep); @@ -284,12 +284,12 @@ public: void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant); Variant get_state(PhysicsServer3D::BodyState p_state) const; - void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); void apply_central_impulse(const Vector3 &p_impulse); + void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); void apply_torque_impulse(const Vector3 &p_impulse); - void apply_force(const Vector3 &p_force, const Vector3 &p_pos); void apply_central_force(const Vector3 &p_force); + void apply_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()); void apply_torque(const Vector3 &p_torque); void set_applied_force(const Vector3 &p_force); diff --git a/modules/camera/camera_osx.mm b/modules/camera/camera_osx.mm index 9a72174723..306632a016 100644 --- a/modules/camera/camera_osx.mm +++ b/modules/camera/camera_osx.mm @@ -313,7 +313,12 @@ MyDeviceNotifications *device_notifications = nil; // CameraOSX - Subclass for our camera server on OSX void CameraOSX::update_feeds() { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101500 + AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeExternalUnknown, AVCaptureDeviceTypeBuiltInWideAngleCamera, nil] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; + NSArray *devices = session.devices; +#else NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; +#endif // remove devices that are gone.. for (int i = feeds.size() - 1; i >= 0; i--) { @@ -325,7 +330,6 @@ void CameraOSX::update_feeds() { }; }; - // add new devices.. for (AVCaptureDevice *device in devices) { bool found = false; for (int i = 0; i < feeds.size() && !found; i++) { diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp index d0c9bf5d38..6c0a3a4ca3 100644 --- a/modules/csg/csg.cpp +++ b/modules/csg/csg.cpp @@ -523,7 +523,7 @@ void CSGBrushOperation::MeshMerge::_add_distance(List<real_t> &r_intersectionsA, // Check if distance exists. for (const List<real_t>::Element *E = intersections.front(); E; E = E->next()) { - if (Math::abs(**E - p_distance) < vertex_snap) { + if (Math::is_equal_approx(**E, p_distance)) { return; } } @@ -1068,15 +1068,6 @@ void CSGBrushOperation::Build2DFaces::_find_edge_intersections(const Vector2 p_s break; } - // Don't create degenerate triangles. - Vector2 split_edge1[2] = { vertices[new_vertex_idx].point, edge_points[0] }; - Vector2 split_edge2[2] = { vertices[new_vertex_idx].point, edge_points[1] }; - Vector2 new_edge[2] = { vertices[new_vertex_idx].point, vertices[opposite_vertex_idx].point }; - if (are_segements_parallel(split_edge1, new_edge, vertex_snap2) && - are_segements_parallel(split_edge2, new_edge, vertex_snap2)) { - break; - } - // If opposite point is on the segemnt, add its index to segment indices too. Vector2 closest_point = Geometry2D::get_closest_point_to_segment(vertices[opposite_vertex_idx].point, p_segment_points); if ((closest_point - vertices[opposite_vertex_idx].point).length_squared() < vertex_snap2) { diff --git a/modules/denoise/config.py b/modules/denoise/config.py index 091d7643c0..49a1f036ed 100644 --- a/modules/denoise/config.py +++ b/modules/denoise/config.py @@ -5,7 +5,7 @@ def can_build(env, platform): # as doing lightmap generation and denoising on Android or HTML5 # would be a bit far-fetched. desktop_platforms = ["linuxbsd", "osx", "windows"] - return env["tools"] and platform in desktop_platforms and env["bits"] == "64" + return env["tools"] and platform in desktop_platforms and env["bits"] == "64" and env["arch"] != "arm64" def configure(env): diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 3d747ba41e..bb2da70c3a 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -291,8 +291,26 @@ bool GDNative::initialize() { return false; } #ifdef IPHONE_ENABLED - // on iOS we use static linking + // On iOS we use static linking by default. String path = ""; + + // On iOS dylibs is not allowed, but can be replaced with .framework or .xcframework. + // If they are used, we can run dlopen on them. + // They should be located under Frameworks directory, so we need to replace library path. + if (!lib_path.ends_with(".a")) { + path = ProjectSettings::get_singleton()->globalize_path(lib_path); + + if (!FileAccess::exists(path)) { + String lib_name = lib_path.get_basename().get_file(); + String framework_path_format = "Frameworks/$name.framework/$name"; + + Dictionary format_dict; + format_dict["name"] = lib_name; + String framework_path = framework_path_format.format(format_dict, "$_"); + + path = OS::get_singleton()->get_executable_path().get_base_dir().plus_file(framework_path); + } + } #elif defined(ANDROID_ENABLED) // On Android dynamic libraries are located separately from resource assets, // we should pass library name to dlopen(). The library name is flattened diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 724a4b56cb..8b0c7474e8 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -277,13 +277,6 @@ godot_int GDAPI godot_string_findn_from(const godot_string *p_self, godot_string return self->findn(*what, p_from); } -godot_int GDAPI godot_string_find_last(const godot_string *p_self, godot_string p_what) { - const String *self = (const String *)p_self; - String *what = (String *)&p_what; - - return self->find_last(*what); -} - godot_string GDAPI godot_string_format(const godot_string *p_self, const godot_variant *p_values) { const String *self = (const String *)p_self; const Variant *values = (const Variant *)p_values; @@ -613,19 +606,19 @@ int64_t GDAPI godot_string_char_to_int64_with_len(const wchar_t *p_str, int p_le int64_t GDAPI godot_string_hex_to_int64(const godot_string *p_self) { const String *self = (const String *)p_self; - return self->hex_to_int64(false); + return self->hex_to_int(false); } int64_t GDAPI godot_string_hex_to_int64_with_prefix(const godot_string *p_self) { const String *self = (const String *)p_self; - return self->hex_to_int64(); + return self->hex_to_int(); } int64_t GDAPI godot_string_to_int64(const godot_string *p_self) { const String *self = (const String *)p_self; - return self->to_int64(); + return self->to_int(); } double GDAPI godot_string_unicode_char_to_double(const wchar_t *p_str, const wchar_t **r_end) { diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index ccd8d2041c..1284ebbd66 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -3825,14 +3825,6 @@ ] }, { - "name": "godot_string_find_last", - "return_type": "godot_int", - "arguments": [ - ["const godot_string *", "p_self"], - ["godot_string", "p_what"] - ] - }, - { "name": "godot_string_format", "return_type": "godot_string", "arguments": [ diff --git a/modules/gdnative/gdnative_library_editor_plugin.cpp b/modules/gdnative/gdnative_library_editor_plugin.cpp index 5896da4640..1d4d188f23 100644 --- a/modules/gdnative/gdnative_library_editor_plugin.cpp +++ b/modules/gdnative/gdnative_library_editor_plugin.cpp @@ -127,15 +127,24 @@ void GDNativeLibraryEditor::_on_item_button(Object *item, int column, int id) { String section = (id == BUTTON_SELECT_DEPENDENCES || id == BUTTON_CLEAR_DEPENDENCES) ? "dependencies" : "entry"; if (id == BUTTON_SELECT_LIBRARY || id == BUTTON_SELECT_DEPENDENCES) { + TreeItem *treeItem = Object::cast_to<TreeItem>(item)->get_parent(); EditorFileDialog::FileMode mode = EditorFileDialog::FILE_MODE_OPEN_FILE; if (id == BUTTON_SELECT_DEPENDENCES) { mode = EditorFileDialog::FILE_MODE_OPEN_FILES; + } else if (treeItem->get_text(0) == "iOS") { + mode = EditorFileDialog::FILE_MODE_OPEN_ANY; } file_dialog->set_meta("target", target); file_dialog->set_meta("section", section); file_dialog->clear_filters(); - file_dialog->add_filter(Object::cast_to<TreeItem>(item)->get_parent()->get_metadata(0)); + + String filter_string = treeItem->get_metadata(0); + Vector<String> filters = filter_string.split(",", false, 0); + for (int i = 0; i < filters.size(); i++) { + file_dialog->add_filter(filters[i]); + } + file_dialog->set_file_mode(mode); file_dialog->popup_centered_ratio(); @@ -309,7 +318,9 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { platform_ios.name = "iOS"; platform_ios.entries.push_back("armv7"); platform_ios.entries.push_back("arm64"); - platform_ios.library_extension = "*.dylib"; + // iOS can use both Static and Dynamic libraries. + // Frameworks is actually a folder with files. + platform_ios.library_extension = "*.framework; Framework, *.xcframework; Binary Framework, *.a; Static Library, *.dylib; Dynamic Library"; platforms["iOS"] = platform_ios; } @@ -360,6 +371,7 @@ GDNativeLibraryEditor::GDNativeLibraryEditor() { //file_dialog->set_resizable(true); add_child(file_dialog); file_dialog->connect("file_selected", callable_mp(this, &GDNativeLibraryEditor::_on_library_selected)); + file_dialog->connect("dir_selected", callable_mp(this, &GDNativeLibraryEditor::_on_library_selected)); file_dialog->connect("files_selected", callable_mp(this, &GDNativeLibraryEditor::_on_dependencies_selected)); new_architecture_dialog = memnew(ConfirmationDialog); diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index 608978db76..dfd4fcab89 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -111,7 +111,6 @@ godot_int GDAPI godot_string_findmk_from(const godot_string *p_self, const godot godot_int GDAPI godot_string_findmk_from_in_place(const godot_string *p_self, const godot_array *p_keys, godot_int p_from, godot_int *r_key); godot_int GDAPI godot_string_findn(const godot_string *p_self, godot_string p_what); godot_int GDAPI godot_string_findn_from(const godot_string *p_self, godot_string p_what, godot_int p_from); -godot_int GDAPI godot_string_find_last(const godot_string *p_self, godot_string p_what); godot_string GDAPI godot_string_format(const godot_string *p_self, const godot_variant *p_values); godot_string GDAPI godot_string_format_with_custom_placeholder(const godot_string *p_self, const godot_variant *p_values, const char *p_placeholder); godot_string GDAPI godot_string_hex_encode_buffer(const uint8_t *p_buffer, godot_int p_len); diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index 06b9534fce..94aa2125c2 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -1853,7 +1853,7 @@ void NativeReloadNode::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_APPLICATION_FOCUS_OUT: { if (unloaded) { break; } @@ -1887,7 +1887,7 @@ void NativeReloadNode::_notification(int p_what) { } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_APPLICATION_FOCUS_IN: { if (!unloaded) { break; } diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 136af5bd1e..d1b1513ac3 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -142,47 +142,85 @@ void GDNativeExportPlugin::_export_file(const String &p_path, const String &p_ty } } + // Add symbols for staticaly linked libraries on iOS if (p_features.has("iOS")) { - // Register symbols in the "fake" dynamic lookup table, because dlsym does not work well on iOS. - LibrarySymbol expected_symbols[] = { - { "gdnative_init", true }, - { "gdnative_terminate", false }, - { "nativescript_init", false }, - { "nativescript_frame", false }, - { "nativescript_thread_enter", false }, - { "nativescript_thread_exit", false }, - { "gdnative_singleton", false } - }; - String declare_pattern = "extern \"C\" void $name(void)$weak;\n"; - String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" - "extern void add_ios_init_callback(void (*cb)());\n"; - String linker_flags = ""; - for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { - String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; - String code = declare_pattern.replace("$name", full_name); - code = code.replace("$weak", expected_symbols[i].is_required ? "" : " __attribute__((weak))"); - additional_code += code; - - if (!expected_symbols[i].is_required) { - if (linker_flags.length() > 0) { - linker_flags += " "; + bool should_fake_dynamic = false; + + List<String> entry_keys; + config->get_section_keys("entry", &entry_keys); + + for (List<String>::Element *E = entry_keys.front(); E; E = E->next()) { + String key = E->get(); + + Vector<String> tags = key.split("."); + + bool skip = false; + for (int i = 0; i < tags.size(); i++) { + bool has_feature = p_features.has(tags[i]); + + if (!has_feature) { + skip = true; + break; } - linker_flags += "-Wl,-U,_" + full_name; } - } - additional_code += String("void $prefixinit() {\n").replace("$prefix", lib->get_symbol_prefix()); - String register_pattern = " if (&$name) register_dynamic_symbol((char *)\"$name\", (void *)$name);\n"; - for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { - String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; - additional_code += register_pattern.replace("$name", full_name); + if (skip) { + continue; + } + + String entry_lib_path = config->get_value("entry", key); + if (entry_lib_path.begins_with("res://") && entry_lib_path.ends_with(".a")) { + // If we find static library that was used for export + // we should add a fake loopup table. + // In case of dynamic library being used, + // this symbols will not cause any issues with library loading. + should_fake_dynamic = true; + break; + } } - additional_code += "}\n"; - additional_code += String("struct $prefixstruct {$prefixstruct() {add_ios_init_callback($prefixinit);}};\n").replace("$prefix", lib->get_symbol_prefix()); - additional_code += String("$prefixstruct $prefixstruct_instance;\n").replace("$prefix", lib->get_symbol_prefix()); - add_ios_cpp_code(additional_code); - add_ios_linker_flags(linker_flags); + if (should_fake_dynamic) { + // Register symbols in the "fake" dynamic lookup table, because dlsym does not work well on iOS. + LibrarySymbol expected_symbols[] = { + { "gdnative_init", true }, + { "gdnative_terminate", false }, + { "nativescript_init", false }, + { "nativescript_frame", false }, + { "nativescript_thread_enter", false }, + { "nativescript_thread_exit", false }, + { "gdnative_singleton", false } + }; + String declare_pattern = "extern \"C\" void $name(void)$weak;\n"; + String additional_code = "extern void register_dynamic_symbol(char *name, void *address);\n" + "extern void add_ios_init_callback(void (*cb)());\n"; + String linker_flags = ""; + for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { + String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; + String code = declare_pattern.replace("$name", full_name); + code = code.replace("$weak", expected_symbols[i].is_required ? "" : " __attribute__((weak))"); + additional_code += code; + + if (!expected_symbols[i].is_required) { + if (linker_flags.length() > 0) { + linker_flags += " "; + } + linker_flags += "-Wl,-U,_" + full_name; + } + } + + additional_code += String("void $prefixinit() {\n").replace("$prefix", lib->get_symbol_prefix()); + String register_pattern = " if (&$name) register_dynamic_symbol((char *)\"$name\", (void *)$name);\n"; + for (unsigned long i = 0; i < sizeof(expected_symbols) / sizeof(expected_symbols[0]); ++i) { + String full_name = lib->get_symbol_prefix() + expected_symbols[i].name; + additional_code += register_pattern.replace("$name", full_name); + } + additional_code += "}\n"; + additional_code += String("struct $prefixstruct {$prefixstruct() {add_ios_init_callback($prefixinit);}};\n").replace("$prefix", lib->get_symbol_prefix()); + additional_code += String("$prefixstruct $prefixstruct_instance;\n").replace("$prefix", lib->get_symbol_prefix()); + + add_ios_cpp_code(additional_code); + add_ios_linker_flags(linker_flags); + } } } diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index 9d9c5b6473..fe7c10cad9 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -214,6 +214,11 @@ void VideoStreamPlaybackGDNative::cleanup() { if (pcm) { memfree(pcm); } + if (file) { + file->close(); + memdelete(file); + file = nullptr; + } pcm = nullptr; time = 0; num_channels = -1; diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index be159b6407..f04cb4b4c3 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -619,11 +619,11 @@ <argument index="0" name="path" type="String"> </argument> <description> - Loads a resource from the filesystem located at [code]path[/code]. - [b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing [b]Copy Path[/b]. + Loads a resource from the filesystem located at [code]path[/code]. The resource is loaded on the method call (unless it's referenced already elsewhere, e.g. in another script or in the scene), which might cause slight delay, especially when loading scenes. To avoid unnecessary delays when loading something multiple times, either store the resource in a variable or use [method preload]. + [b]Note:[/b] Resource paths can be obtained by right-clicking on a resource in the FileSystem dock and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script. [codeblock] - # Load a scene called main located in the root of the project directory. - var main = load("res://main.tscn") + # Load a scene called main located in the root of the project directory and cache it in a variable. + var main = load("res://main.tscn") # main will contain a PackedScene resource. [/codeblock] [b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code]. </description> @@ -797,11 +797,11 @@ <argument index="0" name="path" type="String"> </argument> <description> - Returns a resource from the filesystem that is loaded during script parsing. - [b]Note:[/b] Resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path". + Returns a [Resource] from the filesystem located at [code]path[/code]. The resource is loaded during script parsing, i.e. is loaded with the script and [method preload] effectively acts as a reference to that resource. Note that the method requires a constant path. If you want to load a resource from a dynamic/variable path, use [method load]. + [b]Note:[/b] Resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path" or by dragging the file from the FileSystem dock into the script. [codeblock] - # Load a scene called main located in the root of the project directory. - var main = preload("res://main.tscn") + # Instance a scene. + var diamond = preload("res://diamond.tscn").instance() [/codeblock] </description> </method> diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp new file mode 100644 index 0000000000..a1b18978fc --- /dev/null +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp @@ -0,0 +1,178 @@ +/*************************************************************************/ +/* gdscript_translation_parser_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "gdscript_translation_parser_plugin.h" + +#include "core/io/resource_loader.h" +#include "modules/gdscript/gdscript.h" + +void GDScriptEditorTranslationParserPlugin::get_recognized_extensions(List<String> *r_extensions) const { + GDScriptLanguage::get_singleton()->get_recognized_extensions(r_extensions); +} + +Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Vector<String> *r_extracted_strings) { + List<String> extensions; + get_recognized_extensions(&extensions); + bool extension_valid = false; + for (auto E = extensions.front(); E; E = E->next()) { + if (p_path.get_extension() == E->get()) { + extension_valid = true; + break; + } + } + + if (!extension_valid) { + Vector<String> temp; + for (auto E = extensions.front(); E; E = E->next()) { + temp.push_back(E->get()); + } + String valid_extensions = String(", ").join(temp); + ERR_PRINT("Argument p_path \"" + p_path + "\" has wrong extension. List of valid extensions: " + valid_extensions); + return ERR_INVALID_PARAMETER; + } + + Error err; + RES loaded_res = ResourceLoader::load(p_path, "", false, &err); + if (err) { + ERR_PRINT("Failed to load " + p_path); + return err; + } + + Ref<GDScript> gdscript = loaded_res; + parse_text(gdscript->get_source_code(), r_extracted_strings); + + return OK; +} + +void GDScriptEditorTranslationParserPlugin::parse_text(const String &p_text, Vector<String> *r_extracted_strings) { + // Parse and match all GDScript function API that involves translation string. + // E.g get_node("Label").text = "something", var test = tr("something"), "something" will be matched and collected. + + Vector<String> parsed_strings; + + // Search translation strings with RegEx. + regex.clear(); + regex.compile(String("|").join(patterns)); + Array results = regex.search_all(p_text); + _get_captured_strings(results, &parsed_strings); + + // Special handling for FileDialog. + Vector<String> temp; + _parse_file_dialog(p_text, &temp); + parsed_strings.append_array(temp); + + // Filter out / and + + String filter = "(?:\\\\\\n|\"[\\s\\\\]*\\+\\s*\")"; + regex.clear(); + regex.compile(filter); + for (int i = 0; i < parsed_strings.size(); i++) { + parsed_strings.set(i, regex.sub(parsed_strings[i], "", true)); + } + + r_extracted_strings->append_array(parsed_strings); +} + +void GDScriptEditorTranslationParserPlugin::_parse_file_dialog(const String &p_source_code, Vector<String> *r_output) { + // FileDialog API has the form .filters = PackedStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]). + // First filter: Get "*.png ; PNG Images", "*.gd ; GDScript Files" from PackedStringArray. + regex.clear(); + regex.compile(String("|").join(file_dialog_patterns)); + Array results = regex.search_all(p_source_code); + + Vector<String> temp; + _get_captured_strings(results, &temp); + String captured_strings = String(",").join(temp); + + // Second filter: Get the texts after semicolon from "*.png ; PNG Images","*.gd ; GDScript Files". + String second_filter = "\"[^;]+;" + text + "\""; + regex.clear(); + regex.compile(second_filter); + results = regex.search_all(captured_strings); + _get_captured_strings(results, r_output); + for (int i = 0; i < r_output->size(); i++) { + r_output->set(i, r_output->get(i).strip_edges()); + } +} + +void GDScriptEditorTranslationParserPlugin::_get_captured_strings(const Array &p_results, Vector<String> *r_output) { + Ref<RegExMatch> result; + for (int i = 0; i < p_results.size(); i++) { + result = p_results[i]; + for (int j = 0; j < result->get_group_count(); j++) { + String s = result->get_string(j + 1); + // Prevent reading text with only spaces. + if (!s.strip_edges().empty()) { + r_output->push_back(s); + } + } + } +} + +GDScriptEditorTranslationParserPlugin::GDScriptEditorTranslationParserPlugin() { + // Regex search pattern templates. + // The extra complication in the regex pattern is to ensure that the matching works when users write over multiple lines, use tabs etc. + const String dot = "\\.[\\s\\\\]*"; + const String str_assign_template = "[\\s\\\\]*=[\\s\\\\]*\"" + text + "\""; + const String first_arg_template = "[\\s\\\\]*\\([\\s\\\\]*\"" + text + "\"[\\s\\S]*?\\)"; + const String second_arg_template = "[\\s\\\\]*\\([\\s\\S]+?,[\\s\\\\]*\"" + text + "\"[\\s\\S]*?\\)"; + + // Common patterns. + patterns.push_back("tr" + first_arg_template); + patterns.push_back(dot + "text" + str_assign_template); + patterns.push_back(dot + "placeholder_text" + str_assign_template); + patterns.push_back(dot + "hint_tooltip" + str_assign_template); + patterns.push_back(dot + "set_text" + first_arg_template); + patterns.push_back(dot + "set_tooltip" + first_arg_template); + patterns.push_back(dot + "set_placeholder" + first_arg_template); + + // Tabs and TabContainer API. + patterns.push_back(dot + "set_tab_title" + second_arg_template); + patterns.push_back(dot + "add_tab" + first_arg_template); + + // PopupMenu API. + patterns.push_back(dot + "add_check_item" + first_arg_template); + patterns.push_back(dot + "add_icon_check_item" + second_arg_template); + patterns.push_back(dot + "add_icon_item" + second_arg_template); + patterns.push_back(dot + "add_icon_radio_check_item" + second_arg_template); + patterns.push_back(dot + "add_item" + first_arg_template); + patterns.push_back(dot + "add_multistate_item" + first_arg_template); + patterns.push_back(dot + "add_radio_check_item" + first_arg_template); + patterns.push_back(dot + "add_separator" + first_arg_template); + patterns.push_back(dot + "add_submenu_item" + first_arg_template); + patterns.push_back(dot + "set_item_text" + second_arg_template); + //patterns.push_back(dot + "set_item_tooltip" + second_arg_template); //no tr() behind this function. might be bug. + + // FileDialog API - special case. + const String fd_text = "((?:[\\s\\\\]*\"(?:[^\"\\\\]|\\\\[\\s\\S])*(?:\"[\\s\\\\]*\\+[\\s\\\\]*\"(?:[^\"\\\\]|\\\\[\\s\\S])*)*\"[\\s\\\\]*,?)*)"; + const String packed_string_array = "[\\s\\\\]*PackedStringArray[\\s\\\\]*\\([\\s\\\\]*\\[" + fd_text + "\\][\\s\\\\]*\\)"; + file_dialog_patterns.push_back(dot + "add_filter[\\s\\\\]*\\(" + fd_text + "[\\s\\\\]*\\)"); + file_dialog_patterns.push_back(dot + "filters[\\s\\\\]*=" + packed_string_array); + file_dialog_patterns.push_back(dot + "set_filters[\\s\\\\]*\\(" + packed_string_array + "[\\s\\\\]*\\)"); +} diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.h b/modules/gdscript/editor/gdscript_translation_parser_plugin.h new file mode 100644 index 0000000000..ef967845b9 --- /dev/null +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* gdscript_translation_parser_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H +#define GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H + +#include "editor/editor_translation_parser.h" +#include "modules/regex/regex.h" + +class GDScriptEditorTranslationParserPlugin : public EditorTranslationParserPlugin { + GDCLASS(GDScriptEditorTranslationParserPlugin, EditorTranslationParserPlugin); + + // Regex and search patterns that are used to match translation strings. + const String text = "((?:[^\"\\\\]|\\\\[\\s\\S])*(?:\"[\\s\\\\]*\\+[\\s\\\\]*\"(?:[^\"\\\\]|\\\\[\\s\\S])*)*)"; + RegEx regex; + Vector<String> patterns; + Vector<String> file_dialog_patterns; + + void _parse_file_dialog(const String &p_source_code, Vector<String> *r_output); + void _get_captured_strings(const Array &p_results, Vector<String> *r_output); + +public: + virtual Error parse_file(const String &p_path, Vector<String> *r_extracted_strings); + virtual void parse_text(const String &p_text, Vector<String> *r_extracted_strings); + virtual void get_recognized_extensions(List<String> *r_extensions) const; + + GDScriptEditorTranslationParserPlugin(); +}; + +#endif // GDSCRIPT_TRANSLATION_PARSER_PLUGIN_H diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 2db42601c6..82def3f877 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -952,16 +952,16 @@ void GDScriptTokenizerText::_advance() { INCPOS(i); if (hexa_found) { - int64_t val = str.hex_to_int64(); + int64_t val = str.hex_to_int(); _make_constant(val); } else if (bin_found) { - int64_t val = str.bin_to_int64(); + int64_t val = str.bin_to_int(); _make_constant(val); } else if (period_found || exponent_found) { double val = str.to_double(); _make_constant(val); } else { - int64_t val = str.to_int64(); + int64_t val = str.to_int(); _make_constant(val); } diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 0625123530..53e760ffa7 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -46,7 +46,9 @@ Ref<ResourceFormatSaverGDScript> resource_saver_gd; #include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" +#include "editor/editor_translation_parser.h" #include "editor/gdscript_highlighter.h" +#include "editor/gdscript_translation_parser_plugin.h" #ifndef GDSCRIPT_NO_LSP #include "core/engine.h" @@ -164,6 +166,10 @@ void register_gdscript_types() { #ifdef TOOLS_ENABLED ScriptEditor::register_create_syntax_highlighter_function(GDScriptSyntaxHighlighter::create); EditorNode::add_init_callback(_editor_init); + + Ref<GDScriptEditorTranslationParserPlugin> gdscript_translation_parser_plugin; + gdscript_translation_parser_plugin.instance(); + EditorTranslationParser::get_singleton()->add_parser(gdscript_translation_parser_plugin, EditorTranslationParser::STANDARD); #endif // TOOLS_ENABLED } diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml index a213069e19..79220da7c2 100644 --- a/modules/gridmap/doc_classes/GridMap.xml +++ b/modules/gridmap/doc_classes/GridMap.xml @@ -43,27 +43,19 @@ <method name="get_cell_item" qualifiers="const"> <return type="int"> </return> - <argument index="0" name="x" type="int"> - </argument> - <argument index="1" name="y" type="int"> - </argument> - <argument index="2" name="z" type="int"> + <argument index="0" name="position" type="Vector3i"> </argument> <description> - The [MeshLibrary] item index located at the grid-based X, Y and Z coordinates. If the cell is empty, [constant INVALID_CELL_ITEM] will be returned. + The [MeshLibrary] item index located at the given grid coordinates. If the cell is empty, [constant INVALID_CELL_ITEM] will be returned. </description> </method> <method name="get_cell_item_orientation" qualifiers="const"> <return type="int"> </return> - <argument index="0" name="x" type="int"> - </argument> - <argument index="1" name="y" type="int"> - </argument> - <argument index="2" name="z" type="int"> + <argument index="0" name="position" type="Vector3i"> </argument> <description> - The orientation of the cell at the grid-based X, Y and Z coordinates. -1 is returned if the cell is empty. + The orientation of the cell at the given grid coordinates. [code]-1[/code] is returned if the cell is empty. </description> </method> <method name="get_collision_layer_bit" qualifiers="const"> @@ -111,11 +103,7 @@ <method name="map_to_world" qualifiers="const"> <return type="Vector3"> </return> - <argument index="0" name="x" type="int"> - </argument> - <argument index="1" name="y" type="int"> - </argument> - <argument index="2" name="z" type="int"> + <argument index="0" name="map_position" type="Vector3i"> </argument> <description> Returns the position of a grid cell in the GridMap's local coordinate space. @@ -132,18 +120,14 @@ <method name="set_cell_item"> <return type="void"> </return> - <argument index="0" name="x" type="int"> - </argument> - <argument index="1" name="y" type="int"> + <argument index="0" name="position" type="Vector3i"> </argument> - <argument index="2" name="z" type="int"> + <argument index="1" name="item" type="int"> </argument> - <argument index="3" name="item" type="int"> - </argument> - <argument index="4" name="orientation" type="int" default="0"> + <argument index="2" name="orientation" type="int" default="0"> </argument> <description> - Sets the mesh index for the cell referenced by its grid-based X, Y and Z coordinates. + Sets the mesh index for the cell referenced by its grid coordinates. A negative item index such as [constant INVALID_CELL_ITEM] will clear the cell. Optionally, the item's orientation can be passed. For valid orientation values, see [method Basis.get_orthogonal_index]. </description> @@ -185,9 +169,9 @@ </description> </method> <method name="world_to_map" qualifiers="const"> - <return type="Vector3"> + <return type="Vector3i"> </return> - <argument index="0" name="pos" type="Vector3"> + <argument index="0" name="world_position" type="Vector3"> </argument> <description> Returns the coordinates of the grid cell containing the given point. diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 2975a97bfe..ccf1e49693 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -244,26 +244,26 @@ bool GridMap::get_center_z() const { return center_z; } -void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { +void GridMap::set_cell_item(const Vector3i &p_position, int p_item, int p_rot) { if (baked_meshes.size() && !recreating_octants) { //if you set a cell item, baked meshes go good bye clear_baked_meshes(); _recreate_octant_data(); } - ERR_FAIL_INDEX(ABS(p_x), 1 << 20); - ERR_FAIL_INDEX(ABS(p_y), 1 << 20); - ERR_FAIL_INDEX(ABS(p_z), 1 << 20); + ERR_FAIL_INDEX(ABS(p_position.x), 1 << 20); + ERR_FAIL_INDEX(ABS(p_position.y), 1 << 20); + ERR_FAIL_INDEX(ABS(p_position.z), 1 << 20); IndexKey key; - key.x = p_x; - key.y = p_y; - key.z = p_z; + key.x = p_position.x; + key.y = p_position.y; + key.z = p_position.z; OctantKey ok; - ok.x = p_x / octant_size; - ok.y = p_y / octant_size; - ok.z = p_z / octant_size; + ok.x = p_position.x / octant_size; + ok.y = p_position.y / octant_size; + ok.z = p_position.z / octant_size; if (p_item < 0) { //erase @@ -318,15 +318,15 @@ void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { cell_map[key] = c; } -int GridMap::get_cell_item(int p_x, int p_y, int p_z) const { - ERR_FAIL_INDEX_V(ABS(p_x), 1 << 20, INVALID_CELL_ITEM); - ERR_FAIL_INDEX_V(ABS(p_y), 1 << 20, INVALID_CELL_ITEM); - ERR_FAIL_INDEX_V(ABS(p_z), 1 << 20, INVALID_CELL_ITEM); +int GridMap::get_cell_item(const Vector3i &p_position) const { + ERR_FAIL_INDEX_V(ABS(p_position.x), 1 << 20, INVALID_CELL_ITEM); + ERR_FAIL_INDEX_V(ABS(p_position.y), 1 << 20, INVALID_CELL_ITEM); + ERR_FAIL_INDEX_V(ABS(p_position.z), 1 << 20, INVALID_CELL_ITEM); IndexKey key; - key.x = p_x; - key.y = p_y; - key.z = p_z; + key.x = p_position.x; + key.y = p_position.y; + key.z = p_position.z; if (!cell_map.has(key)) { return INVALID_CELL_ITEM; @@ -334,15 +334,15 @@ int GridMap::get_cell_item(int p_x, int p_y, int p_z) const { return cell_map[key].item; } -int GridMap::get_cell_item_orientation(int p_x, int p_y, int p_z) const { - ERR_FAIL_INDEX_V(ABS(p_x), 1 << 20, -1); - ERR_FAIL_INDEX_V(ABS(p_y), 1 << 20, -1); - ERR_FAIL_INDEX_V(ABS(p_z), 1 << 20, -1); +int GridMap::get_cell_item_orientation(const Vector3i &p_position) const { + ERR_FAIL_INDEX_V(ABS(p_position.x), 1 << 20, -1); + ERR_FAIL_INDEX_V(ABS(p_position.y), 1 << 20, -1); + ERR_FAIL_INDEX_V(ABS(p_position.z), 1 << 20, -1); IndexKey key; - key.x = p_x; - key.y = p_y; - key.z = p_z; + key.x = p_position.x; + key.y = p_position.y; + key.z = p_position.z; if (!cell_map.has(key)) { return -1; @@ -350,20 +350,20 @@ int GridMap::get_cell_item_orientation(int p_x, int p_y, int p_z) const { return cell_map[key].rot; } -Vector3 GridMap::world_to_map(const Vector3 &p_world_pos) const { - Vector3 map_pos = p_world_pos / cell_size; - map_pos.x = floor(map_pos.x); - map_pos.y = floor(map_pos.y); - map_pos.z = floor(map_pos.z); - return map_pos; +Vector3i GridMap::world_to_map(const Vector3 &p_world_position) const { + Vector3 map_position = p_world_position / cell_size; + map_position.x = floor(map_position.x); + map_position.y = floor(map_position.y); + map_position.z = floor(map_position.z); + return Vector3i(map_position); } -Vector3 GridMap::map_to_world(int p_x, int p_y, int p_z) const { +Vector3 GridMap::map_to_world(const Vector3i &p_map_position) const { Vector3 offset = _get_offset(); Vector3 world_pos( - p_x * cell_size.x + offset.x, - p_y * cell_size.y + offset.y, - p_z * cell_size.z + offset.z); + p_map_position.x * cell_size.x + offset.x, + p_map_position.y * cell_size.y + offset.y, + p_map_position.z * cell_size.z + offset.z); return world_pos; } @@ -725,7 +725,7 @@ void GridMap::_recreate_octant_data() { Map<IndexKey, Cell> cell_copy = cell_map; _clear_internal(); for (Map<IndexKey, Cell>::Element *E = cell_copy.front(); E; E = E->next()) { - set_cell_item(E->key().x, E->key().y, E->key().z, E->get().item, E->get().rot); + set_cell_item(Vector3i(E->key()), E->get().item, E->get().rot); } recreating_octants = false; } @@ -799,12 +799,12 @@ void GridMap::_bind_methods() { ClassDB::bind_method(D_METHOD("set_octant_size", "size"), &GridMap::set_octant_size); ClassDB::bind_method(D_METHOD("get_octant_size"), &GridMap::get_octant_size); - ClassDB::bind_method(D_METHOD("set_cell_item", "x", "y", "z", "item", "orientation"), &GridMap::set_cell_item, DEFVAL(0)); - ClassDB::bind_method(D_METHOD("get_cell_item", "x", "y", "z"), &GridMap::get_cell_item); - ClassDB::bind_method(D_METHOD("get_cell_item_orientation", "x", "y", "z"), &GridMap::get_cell_item_orientation); + ClassDB::bind_method(D_METHOD("set_cell_item", "position", "item", "orientation"), &GridMap::set_cell_item, DEFVAL(0)); + ClassDB::bind_method(D_METHOD("get_cell_item", "position"), &GridMap::get_cell_item); + ClassDB::bind_method(D_METHOD("get_cell_item_orientation", "position"), &GridMap::get_cell_item_orientation); - ClassDB::bind_method(D_METHOD("world_to_map", "pos"), &GridMap::world_to_map); - ClassDB::bind_method(D_METHOD("map_to_world", "x", "y", "z"), &GridMap::map_to_world); + ClassDB::bind_method(D_METHOD("world_to_map", "world_position"), &GridMap::world_to_map); + ClassDB::bind_method(D_METHOD("map_to_world", "map_position"), &GridMap::map_to_world); ClassDB::bind_method(D_METHOD("_update_octants_callback"), &GridMap::_update_octants_callback); ClassDB::bind_method(D_METHOD("resource_changed", "resource"), &GridMap::resource_changed); diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index 9eb9aee7d1..ca7429ea26 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -59,6 +59,15 @@ class GridMap : public Node3D { return key < p_key.key; } + _FORCE_INLINE_ operator Vector3i() const { + return Vector3i(x, y, z); + } + + IndexKey(Vector3i p_vector) { + x = (int16_t)p_vector.x; + y = (int16_t)p_vector.y; + z = (int16_t)p_vector.z; + } IndexKey() { key = 0; } }; @@ -234,12 +243,12 @@ public: void set_center_z(bool p_enable); bool get_center_z() const; - void set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot = 0); - int get_cell_item(int p_x, int p_y, int p_z) const; - int get_cell_item_orientation(int p_x, int p_y, int p_z) const; + void set_cell_item(const Vector3i &p_position, int p_item, int p_rot = 0); + int get_cell_item(const Vector3i &p_position) const; + int get_cell_item_orientation(const Vector3i &p_position) const; - Vector3 world_to_map(const Vector3 &p_world_pos) const; - Vector3 map_to_world(int p_x, int p_y, int p_z) const; + Vector3i world_to_map(const Vector3 &p_world_position) const; + Vector3 map_to_world(const Vector3i &p_map_position) const; void set_clip(bool p_enabled, bool p_clip_above = true, int p_floor = 0, Vector3::Axis p_axis = Vector3::AXIS_X); diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 1b7ce98721..0e6ec7f520 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -291,15 +291,15 @@ void GridMapEditor::_update_selection_transform() { } else { Vector3 scale = (selection.end - selection.begin + Vector3(1, 1, 1)); scale[edit_axis] = 1.0; - Vector3 pos = selection.begin; - pos[edit_axis] = edit_floor[edit_axis]; + Vector3 position = selection.begin; + position[edit_axis] = edit_floor[edit_axis]; scale *= node->get_cell_size(); - pos *= node->get_cell_size(); + position *= node->get_cell_size(); Transform xf2; xf2.basis.scale(scale); - xf2.origin = pos; + xf2.origin = position; RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); } @@ -414,11 +414,11 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b } if (input_action == INPUT_PASTE) { - paste_indicator.current = Vector3(cell[0], cell[1], cell[2]); + paste_indicator.current = Vector3i(cell[0], cell[1], cell[2]); _update_paste_indicator(); } else if (input_action == INPUT_SELECT) { - selection.current = Vector3(cell[0], cell[1], cell[2]); + selection.current = Vector3i(cell[0], cell[1], cell[2]); if (p_click) { selection.click = selection.current; } @@ -427,7 +427,7 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b return true; } else if (input_action == INPUT_PICK) { - int item = node->get_cell_item(cell[0], cell[1], cell[2]); + int item = node->get_cell_item(Vector3i(cell[0], cell[1], cell[2])); if (item >= 0) { selected_palette = item; mesh_library_palette->set_current(item); @@ -438,23 +438,23 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b } if (input_action == INPUT_PAINT) { SetItem si; - si.pos = Vector3(cell[0], cell[1], cell[2]); + si.position = Vector3i(cell[0], cell[1], cell[2]); si.new_value = selected_palette; si.new_orientation = cursor_rot; - si.old_value = node->get_cell_item(cell[0], cell[1], cell[2]); - si.old_orientation = node->get_cell_item_orientation(cell[0], cell[1], cell[2]); + si.old_value = node->get_cell_item(Vector3i(cell[0], cell[1], cell[2])); + si.old_orientation = node->get_cell_item_orientation(Vector3i(cell[0], cell[1], cell[2])); set_items.push_back(si); - node->set_cell_item(cell[0], cell[1], cell[2], selected_palette, cursor_rot); + node->set_cell_item(Vector3i(cell[0], cell[1], cell[2]), selected_palette, cursor_rot); return true; } else if (input_action == INPUT_ERASE) { SetItem si; - si.pos = Vector3(cell[0], cell[1], cell[2]); + si.position = Vector3i(cell[0], cell[1], cell[2]); si.new_value = -1; si.new_orientation = 0; - si.old_value = node->get_cell_item(cell[0], cell[1], cell[2]); - si.old_orientation = node->get_cell_item_orientation(cell[0], cell[1], cell[2]); + si.old_value = node->get_cell_item(Vector3i(cell[0], cell[1], cell[2])); + si.old_orientation = node->get_cell_item_orientation(Vector3i(cell[0], cell[1], cell[2])); set_items.push_back(si); - node->set_cell_item(cell[0], cell[1], cell[2], -1); + node->set_cell_item(Vector3i(cell[0], cell[1], cell[2]), -1); return true; } @@ -470,8 +470,9 @@ void GridMapEditor::_delete_selection() { for (int i = selection.begin.x; i <= selection.end.x; i++) { for (int j = selection.begin.y; j <= selection.end.y; j++) { for (int k = selection.begin.z; k <= selection.end.z; k++) { - undo_redo->add_do_method(node, "set_cell_item", i, j, k, GridMap::INVALID_CELL_ITEM); - undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k)); + Vector3i selected = Vector3i(i, j, k); + undo_redo->add_do_method(node, "set_cell_item", selected, GridMap::INVALID_CELL_ITEM); + undo_redo->add_undo_method(node, "set_cell_item", selected, node->get_cell_item(selected), node->get_cell_item_orientation(selected)); } } } @@ -489,8 +490,9 @@ void GridMapEditor::_fill_selection() { for (int i = selection.begin.x; i <= selection.end.x; i++) { for (int j = selection.begin.y; j <= selection.end.y; j++) { for (int k = selection.begin.z; k <= selection.end.z; k++) { - undo_redo->add_do_method(node, "set_cell_item", i, j, k, selected_palette, cursor_rot); - undo_redo->add_undo_method(node, "set_cell_item", i, j, k, node->get_cell_item(i, j, k), node->get_cell_item_orientation(i, j, k)); + Vector3i selected = Vector3i(i, j, k); + undo_redo->add_do_method(node, "set_cell_item", selected, selected_palette, cursor_rot); + undo_redo->add_undo_method(node, "set_cell_item", selected, node->get_cell_item(selected), node->get_cell_item_orientation(selected)); } } } @@ -515,7 +517,8 @@ void GridMapEditor::_set_clipboard_data() { for (int i = selection.begin.x; i <= selection.end.x; i++) { for (int j = selection.begin.y; j <= selection.end.y; j++) { for (int k = selection.begin.z; k <= selection.end.z; k++) { - int itm = node->get_cell_item(i, j, k); + Vector3i selected = Vector3i(i, j, k); + int itm = node->get_cell_item(selected); if (itm == GridMap::INVALID_CELL_ITEM) { continue; } @@ -524,8 +527,8 @@ void GridMapEditor::_set_clipboard_data() { ClipboardItem item; item.cell_item = itm; - item.grid_offset = Vector3(i, j, k) - selection.begin; - item.orientation = node->get_cell_item_orientation(i, j, k); + item.grid_offset = Vector3(selected) - selection.begin; + item.orientation = node->get_cell_item_orientation(selected); item.instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world_3d()->get_scenario()); clipboard_items.push_back(item); @@ -583,14 +586,14 @@ void GridMapEditor::_do_paste() { for (List<ClipboardItem>::Element *E = clipboard_items.front(); E; E = E->next()) { ClipboardItem &item = E->get(); - Vector3 pos = rot.xform(item.grid_offset) + paste_indicator.begin + ofs; + Vector3 position = rot.xform(item.grid_offset) + paste_indicator.begin + ofs; Basis orm; orm.set_orthogonal_index(item.orientation); orm = rot * orm; - undo_redo->add_do_method(node, "set_cell_item", pos.x, pos.y, pos.z, item.cell_item, orm.get_orthogonal_index()); - undo_redo->add_undo_method(node, "set_cell_item", pos.x, pos.y, pos.z, node->get_cell_item(pos.x, pos.y, pos.z), node->get_cell_item_orientation(pos.x, pos.y, pos.z)); + undo_redo->add_do_method(node, "set_cell_item", position, item.cell_item, orm.get_orthogonal_index()); + undo_redo->add_undo_method(node, "set_cell_item", position, node->get_cell_item(position), node->get_cell_item_orientation(position)); } if (reselect) { @@ -667,11 +670,11 @@ bool GridMapEditor::forward_spatial_input_event(Camera3D *p_camera, const Ref<In undo_redo->create_action(TTR("GridMap Paint")); for (List<SetItem>::Element *E = set_items.front(); E; E = E->next()) { const SetItem &si = E->get(); - undo_redo->add_do_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.new_value, si.new_orientation); + undo_redo->add_do_method(node, "set_cell_item", si.position, si.new_value, si.new_orientation); } for (List<SetItem>::Element *E = set_items.back(); E; E = E->prev()) { const SetItem &si = E->get(); - undo_redo->add_undo_method(node, "set_cell_item", si.pos.x, si.pos.y, si.pos.z, si.old_value, si.old_orientation); + undo_redo->add_undo_method(node, "set_cell_item", si.position, si.old_value, si.old_orientation); } undo_redo->commit_action(); diff --git a/modules/gridmap/grid_map_editor_plugin.h b/modules/gridmap/grid_map_editor_plugin.h index 0ae9b27833..84b68ba6e7 100644 --- a/modules/gridmap/grid_map_editor_plugin.h +++ b/modules/gridmap/grid_map_editor_plugin.h @@ -33,7 +33,6 @@ #include "editor/editor_node.h" #include "editor/editor_plugin.h" -#include "editor/pane_drag.h" #include "grid_map.h" class Node3DEditorPlugin; @@ -85,7 +84,7 @@ class GridMapEditor : public VBoxContainer { Label *spin_box_label; struct SetItem { - Vector3 pos; + Vector3i position; int new_value; int new_orientation; int old_value; diff --git a/modules/mono/build_scripts/solution_builder.py b/modules/mono/build_scripts/solution_builder.py index 371819fd72..03f4e57f02 100644 --- a/modules/mono/build_scripts/solution_builder.py +++ b/modules/mono/build_scripts/solution_builder.py @@ -142,9 +142,7 @@ def build_solution(env, solution_path, build_config, extra_msbuild_args=[]): # Build solution - targets = ["Restore", "Build"] - - msbuild_args += [solution_path, "/t:%s" % ",".join(targets), "/p:Configuration=" + build_config] + msbuild_args += [solution_path, "/restore", "/t:Build", "/p:Configuration=" + build_config] msbuild_args += extra_msbuild_args run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild") diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs index e55558c100..34e42489eb 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildSystem.cs @@ -47,19 +47,14 @@ namespace GodotTools.Build private static bool PrintBuildOutput => (bool)EditorSettings.GetSetting("mono/builds/print_build_output"); - private static Process LaunchBuild(string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) + private static Process LaunchBuild(BuildInfo buildInfo) { (string msbuildPath, BuildTool buildTool) = MsBuildFinder.FindMsBuild(); if (msbuildPath == null) throw new FileNotFoundException("Cannot find the MSBuild executable."); - var customPropertiesList = new List<string>(); - - if (customProperties != null) - customPropertiesList.AddRange(customProperties); - - string compilerArgs = BuildArguments(buildTool, solution, targets, config, loggerOutputDir, customPropertiesList); + string compilerArgs = BuildArguments(buildTool, buildInfo); var startInfo = new ProcessStartInfo(msbuildPath, compilerArgs); @@ -100,19 +95,7 @@ namespace GodotTools.Build public static int Build(BuildInfo buildInfo) { - return Build(buildInfo.Solution, buildInfo.Targets, buildInfo.Configuration, - buildInfo.LogsDirPath, buildInfo.CustomProperties); - } - - public static Task<int> BuildAsync(BuildInfo buildInfo) - { - return BuildAsync(buildInfo.Solution, buildInfo.Targets, buildInfo.Configuration, - buildInfo.LogsDirPath, buildInfo.CustomProperties); - } - - public static int Build(string solution, string[] targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) - { - using (var process = LaunchBuild(solution, targets, config, loggerOutputDir, customProperties)) + using (var process = LaunchBuild(buildInfo)) { process.WaitForExit(); @@ -120,9 +103,9 @@ namespace GodotTools.Build } } - public static async Task<int> BuildAsync(string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties = null) + public static async Task<int> BuildAsync(BuildInfo buildInfo) { - using (var process = LaunchBuild(solution, targets, config, loggerOutputDir, customProperties)) + using (var process = LaunchBuild(buildInfo)) { await process.WaitForExitAsync(); @@ -130,17 +113,18 @@ namespace GodotTools.Build } } - private static string BuildArguments(BuildTool buildTool, string solution, IEnumerable<string> targets, string config, string loggerOutputDir, IEnumerable<string> customProperties) + private static string BuildArguments(BuildTool buildTool, BuildInfo buildInfo) { string arguments = string.Empty; if (buildTool == BuildTool.DotnetCli) arguments += "msbuild "; // `dotnet msbuild` command - arguments += $@"""{solution}"" /v:normal /t:{string.Join(",", targets)} ""/p:{"Configuration=" + config}"" " + - $@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{loggerOutputDir}"""; + arguments += $@"""{buildInfo.Solution}"" /t:{string.Join(",", buildInfo.Targets)} " + + $@"""/p:{"Configuration=" + buildInfo.Configuration}"" /v:normal " + + $@"""/l:{typeof(GodotBuildLogger).FullName},{GodotBuildLogger.AssemblyPath};{buildInfo.LogsDirPath}"""; - foreach (string customProperty in customProperties) + foreach (string customProperty in buildInfo.CustomProperties) { arguments += " /p:" + customProperty; } diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs index cca0983c01..ab090c46e7 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildInfo.cs @@ -12,6 +12,7 @@ namespace GodotTools public string Solution { get; } public string[] Targets { get; } public string Configuration { get; } + public bool Restore { get; } public Array<string> CustomProperties { get; } = new Array<string>(); // TODO Use List once we have proper serialization public string LogsDirPath => Path.Combine(GodotSharpDirs.BuildLogsDirs, $"{Solution.MD5Text()}_{Configuration}"); @@ -39,11 +40,12 @@ namespace GodotTools { } - public BuildInfo(string solution, string[] targets, string configuration) + public BuildInfo(string solution, string[] targets, string configuration, bool restore) { Solution = solution; Targets = targets; Configuration = configuration; + Restore = restore; } } } diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs index 598787ba03..0974d23176 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs @@ -175,7 +175,7 @@ namespace GodotTools { pr.Step("Building project solution", 0); - var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets: new[] {"Restore", "Build"}, config); + var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets: new[] {"Build"}, config, restore: true); bool escapeNeedsDoubleBackslash = buildTool == BuildTool.MsBuildMono || buildTool == BuildTool.DotnetCli; diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs index 0106e1f1ac..8596cd24af 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildTab.cs @@ -113,7 +113,7 @@ namespace GodotTools throw new IndexOutOfRangeException("Item list index out of range"); // Get correct issue idx from issue list - int issueIndex = (int)issuesList.GetItemMetadata(idx); + int issueIndex = (int)(long)issuesList.GetItemMetadata(idx); if (issueIndex < 0 || issueIndex >= issues.Count) throw new IndexOutOfRangeException("Issue index out of range"); diff --git a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs index ae05710f4f..b30c857c64 100644 --- a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs +++ b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs @@ -10,7 +10,7 @@ namespace GodotTools public override void _Notification(int what) { - if (what == Node.NotificationWmFocusIn) + if (what == Node.NotificationWmWindowFocusIn) { RestartTimer(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index 9384da0e48..e050d1fdd1 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -84,7 +84,7 @@ namespace Godot public static void Print(params object[] what) { - godot_icall_GD_print(Array.ConvertAll(what, x => x?.ToString())); + godot_icall_GD_print(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null")); } public static void PrintStack() @@ -94,22 +94,22 @@ namespace Godot public static void PrintErr(params object[] what) { - godot_icall_GD_printerr(Array.ConvertAll(what, x => x?.ToString())); + godot_icall_GD_printerr(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null")); } public static void PrintRaw(params object[] what) { - godot_icall_GD_printraw(Array.ConvertAll(what, x => x?.ToString())); + godot_icall_GD_printraw(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null")); } public static void PrintS(params object[] what) { - godot_icall_GD_prints(Array.ConvertAll(what, x => x?.ToString())); + godot_icall_GD_prints(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null")); } public static void PrintT(params object[] what) { - godot_icall_GD_printt(Array.ConvertAll(what, x => x?.ToString())); + godot_icall_GD_printt(Array.ConvertAll(what ?? new object[]{"null"}, x => x != null ? x.ToString() : "null")); } public static float Randf() diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index 27e402d777..abb2761909 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -114,7 +114,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { } void unhandled_exception(MonoException *p_exc) { - mono_unhandled_exception((MonoObject *)p_exc); // prints the exception as well + mono_print_unhandled_exception((MonoObject *)p_exc); if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) { // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 158742846b..92734a0792 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -1035,6 +1035,10 @@ Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_ty } String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc) { + if (p_obj == nullptr) { + return String("null"); + } + ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj)); Variant var = GDMonoMarshal::mono_object_to_variant_no_err(p_obj, type); diff --git a/modules/opensimplex/open_simplex_noise.cpp b/modules/opensimplex/open_simplex_noise.cpp index 00b3d47db9..b08219d258 100644 --- a/modules/opensimplex/open_simplex_noise.cpp +++ b/modules/opensimplex/open_simplex_noise.cpp @@ -110,7 +110,7 @@ Ref<Image> OpenSimplexNoise::get_image(int p_width, int p_height) { for (int i = 0; i < p_height; i++) { for (int j = 0; j < p_width; j++) { - float v = get_noise_2d(i, j); + float v = get_noise_2d(j, i); v = v * 0.5 + 0.5; // Normalize [0..1] uint8_t value = uint8_t(CLAMP(v * 255.0, 0, 255)); wd8[(i * p_width + j) * 4 + 0] = value; diff --git a/modules/opus/SCsub b/modules/opus/SCsub index e51590d808..52c61fa708 100644 --- a/modules/opus/SCsub +++ b/modules/opus/SCsub @@ -227,6 +227,9 @@ if env["builtin_opus"]: env_opus.Append(CPPDEFINES=["OPUS_ARM_OPT"]) elif "arch" in env and env["arch"] == "arm64": env_opus.Append(CPPDEFINES=["OPUS_ARM64_OPT"]) + elif env["platform"] == "osx": + if "arch" in env and env["arch"] == "arm64": + env_opus.Append(CPPDEFINES=["OPUS_ARM64_OPT"]) env_thirdparty = env_opus.Clone() env_thirdparty.disable_warnings() diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp index ce889a4928..1475d24792 100644 --- a/modules/tga/image_loader_tga.cpp +++ b/modules/tga/image_loader_tga.cpp @@ -30,6 +30,8 @@ #include "image_loader_tga.h" +#include "core/error_macros.h" +#include "core/io/file_access_memory.h" #include "core/os/os.h" #include "core/print_string.h" @@ -311,5 +313,17 @@ void ImageLoaderTGA::get_recognized_extensions(List<String> *p_extensions) const p_extensions->push_back("tga"); } +static Ref<Image> _tga_mem_loader_func(const uint8_t *p_png, int p_size) { + FileAccessMemory memfile; + Error open_memfile_error = memfile.open_custom(p_png, p_size); + ERR_FAIL_COND_V_MSG(open_memfile_error, Ref<Image>(), "Could not create memfile for TGA image buffer."); + Ref<Image> img; + img.instance(); + Error load_error = ImageLoaderTGA().load_image(img, &memfile, false, 1.0f); + ERR_FAIL_COND_V_MSG(load_error, Ref<Image>(), "Failed to load TGA image."); + return img; +} + ImageLoaderTGA::ImageLoaderTGA() { + Image::_tga_mem_loader_func = _tga_mem_loader_func; } diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub index dd6866ad0e..d0744fa313 100644 --- a/modules/webm/libvpx/SCsub +++ b/modules/webm/libvpx/SCsub @@ -238,6 +238,7 @@ else: is_x11_or_server_arm = (env["platform"] == "linuxbsd" or env["platform"] == "server") and ( platform.machine().startswith("arm") or platform.machine().startswith("aarch") ) + is_macos_x86 = env["platform"] == "osx" and ("arch" in env and (env["arch"] != "arm64")) is_ios_x86 = env["platform"] == "iphone" and ("arch" in env and env["arch"].startswith("x86")) is_android_x86 = env["platform"] == "android" and env["android_arch"].startswith("x86") if is_android_x86: @@ -248,14 +249,15 @@ else: and ( env["platform"] == "windows" or env["platform"] == "linuxbsd" - or env["platform"] == "osx" or env["platform"] == "haiku" + or is_macos_x86 or is_android_x86 or is_ios_x86 ) ) webm_cpu_arm = ( is_x11_or_server_arm + or (not is_macos_x86 and env["platform"] == "osx") or (not is_ios_x86 and env["platform"] == "iphone") or (not is_android_x86 and env["platform"] == "android") ) diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp index 3900180739..8feaa9af5a 100644 --- a/modules/websocket/websocket_client.cpp +++ b/modules/websocket/websocket_client.cpp @@ -66,7 +66,7 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto } // Port - p_len = host.find_last(":"); + p_len = host.rfind(":"); if (p_len != -1 && p_len == host.find(":")) { port = host.substr(p_len, host.length() - p_len).to_int(); host = host.substr(0, p_len); diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index a663a847c2..474458b00f 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -862,6 +862,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { String tname = string_table[name]; uint32_t attrcount = decode_uint32(&p_manifest[iofs + 20]); iofs += 28; + bool is_focus_aware_metadata = false; for (uint32_t i = 0; i < attrcount; i++) { uint32_t attr_nspace = decode_uint32(&p_manifest[iofs]); @@ -929,9 +930,9 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { } } - if (tname == "meta-data" && attrname == "value" && value == "oculus_focus_aware_value") { + if (tname == "meta-data" && attrname == "value" && is_focus_aware_metadata) { // Update the focus awareness meta-data value - string_table.write[attr_value] = xr_mode_index == /* XRMode.OVR */ 1 && focus_awareness ? "true" : "false"; + encode_uint32(xr_mode_index == /* XRMode.OVR */ 1 && focus_awareness ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]); } if (tname == "meta-data" && attrname == "value" && value == "plugins_value" && !plugins_names.empty()) { @@ -939,6 +940,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { string_table.write[attr_value] = plugins_names; } + is_focus_aware_metadata = tname == "meta-data" && attrname == "name" && value == "com.oculus.vr.focusaware"; iofs += 20; } @@ -1332,7 +1334,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { str = get_project_name(package_name); } else { - String lang = str.substr(str.find_last("-") + 1, str.length()).replace("-", "_"); + String lang = str.substr(str.rfind("-") + 1, str.length()).replace("-", "_"); String prop = "application/config/name_" + lang; if (ProjectSettings::get_singleton()->has_setting(prop)) { str = ProjectSettings::get_singleton()->get(prop); diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index dbf1dc0f3c..48c09552c1 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -45,8 +45,8 @@ android:resizeableActivity="false" tools:ignore="UnusedAttribute" > - <!-- Focus awareness metadata populated at export time if the user enables it in the 'Xr Features' section. --> - <meta-data android:name="com.oculus.vr.focusaware" android:value="oculus_focus_aware_value" /> + <!-- Focus awareness metadata is updated at export time if the user enables it in the 'Xr Features' section. --> + <meta-data android:name="com.oculus.vr.focusaware" android:value="false" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/platform/android/java/app/src/com/godot/game/GodotApp.java b/platform/android/java/app/src/com/godot/game/GodotApp.java index eb884404cd..1af5950cbe 100644 --- a/platform/android/java/app/src/com/godot/game/GodotApp.java +++ b/platform/android/java/app/src/com/godot/game/GodotApp.java @@ -30,11 +30,11 @@ package com.godot.game; -import org.godotengine.godot.Godot; +import org.godotengine.godot.FullScreenGodotApp; /** * Template activity for Godot Android custom builds. * Feel free to extend and modify this class for your custom logic. */ -public class GodotApp extends Godot { +public class GodotApp extends FullScreenGodotApp { } diff --git a/platform/android/java/lib/res/layout/godot_app_layout.xml b/platform/android/java/lib/res/layout/godot_app_layout.xml new file mode 100644 index 0000000000..386ded1c5d --- /dev/null +++ b/platform/android/java/lib/res/layout/godot_app_layout.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/godot_fragment_container" + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java new file mode 100644 index 0000000000..138c2de94c --- /dev/null +++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* FullScreenGodotApp.java */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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. */ +/*************************************************************************/ + +package org.godotengine.godot; + +import android.content.Intent; +import android.os.Bundle; +import android.view.KeyEvent; + +import androidx.fragment.app.FragmentActivity; + +/** + * Base activity for Android apps intending to use Godot as the primary and only screen. + * + * It's also a reference implementation for how to setup and use the {@link Godot} fragment + * within an Android app. + */ +public abstract class FullScreenGodotApp extends FragmentActivity { + protected Godot godotFragment; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.godot_app_layout); + godotFragment = new Godot(); + getSupportFragmentManager().beginTransaction().replace(R.id.godot_fragment_container, godotFragment).setPrimaryNavigationFragment(godotFragment).commitNowAllowingStateLoss(); + } + + @Override + public void onNewIntent(Intent intent) { + if (godotFragment != null) { + godotFragment.onNewIntent(intent); + } + } + + @Override + public void onBackPressed() { + if (godotFragment != null) { + godotFragment.onBackPressed(); + } else { + super.onBackPressed(); + } + } + + @Override + public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) { + if (godotFragment != null && godotFragment.onKeyMultiple(inKeyCode, repeatCount, event)) { + return true; + } + return super.onKeyMultiple(inKeyCode, repeatCount, event); + } +} diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index fcbbc86100..1b55090451 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -30,6 +30,9 @@ package org.godotengine.godot; +import static android.content.Context.MODE_PRIVATE; +import static android.content.Context.WINDOW_SERVICE; + import org.godotengine.godot.input.GodotEditText; import org.godotengine.godot.plugin.GodotPlugin; import org.godotengine.godot.plugin.GodotPluginRegistry; @@ -68,6 +71,7 @@ import android.os.Vibrator; import android.provider.Settings.Secure; import android.view.Display; import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -84,7 +88,7 @@ import android.widget.TextView; import androidx.annotation.CallSuper; import androidx.annotation.Keep; import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.Fragment; import com.google.android.vending.expansion.downloader.DownloadProgressInfo; import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller; @@ -102,7 +106,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; -public abstract class Godot extends FragmentActivity implements SensorEventListener, IDownloaderClient { +public class Godot extends Fragment implements SensorEventListener, IDownloaderClient { private IStub mDownloaderClientStub; private TextView mStatusText; private TextView mProgressFraction; @@ -130,7 +134,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe static private Intent mCurrentIntent; - @Override public void onNewIntent(Intent intent) { mCurrentIntent = intent; } @@ -156,6 +159,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe private String[] command_line; private boolean use_apk_expansion; + private ViewGroup containerLayout; public GodotRenderView mRenderView; private boolean godot_initialized = false; @@ -174,7 +178,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe public ResultCallback result_callback; @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent data) { if (result_callback != null) { result_callback.callback(requestCode, resultCode, data); result_callback = null; @@ -211,27 +215,28 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe */ @Keep private void onVideoInit() { - final FrameLayout layout = new FrameLayout(this); - layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); - setContentView(layout); + final Activity activity = getActivity(); + containerLayout = new FrameLayout(activity); + containerLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // GodotEditText layout - GodotEditText editText = new GodotEditText(this); + GodotEditText editText = new GodotEditText(activity); editText.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); // ...add to FrameLayout - layout.addView(editText); + containerLayout.addView(editText); GodotLib.setup(command_line); final String videoDriver = GodotLib.getGlobal("rendering/quality/driver/driver_name"); if (videoDriver.equals("Vulkan")) { - mRenderView = new GodotVulkanRenderView(this); + mRenderView = new GodotVulkanRenderView(activity, this); } else { - mRenderView = new GodotGLRenderView(this, xrMode, use_32_bits, use_debug_opengl); + mRenderView = new GodotGLRenderView(activity, this, xrMode, use_32_bits, + use_debug_opengl); } View view = mRenderView.getView(); - layout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + containerLayout.addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); editText.setView(mRenderView); io.setEdit(editText); @@ -239,7 +244,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Override public void onGlobalLayout() { Point fullSize = new Point(); - getWindowManager().getDefaultDisplay().getSize(fullSize); + activity.getWindowManager().getDefaultDisplay().getSize(fullSize); Rect gameSize = new Rect(); mRenderView.getView().getWindowVisibleDisplayFrame(gameSize); @@ -262,9 +267,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe // Include the returned non-null views in the Godot view hierarchy. for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { - View pluginView = plugin.onMainCreate(this); + View pluginView = plugin.onMainCreate(activity); if (pluginView != null) { - layout.addView(pluginView); + containerLayout.addView(pluginView); } } } @@ -274,9 +279,9 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Override public void run() { if (p_enabled) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } else { - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } } }); @@ -290,7 +295,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Keep private void vibrate(int durationMs) { if (requestPermission("VIBRATE")) { - Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE); + Vibrator v = (Vibrator)getContext().getSystemService(Context.VIBRATOR_SERVICE); if (v != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { v.vibrate(VibrationEffect.createOneShot(durationMs, VibrationEffect.DEFAULT_AMPLITUDE)); @@ -314,13 +319,16 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe // Using instrumentation is a way of making the whole app process restart, because Android // will kill any process of the same package which was already running. // - Bundle args = new Bundle(); - args.putParcelable("intent", mCurrentIntent); - startInstrumentation(new ComponentName(this, GodotInstrumentation.class), null, args); + final Activity activity = getActivity(); + if (activity != null) { + Bundle args = new Bundle(); + args.putParcelable("intent", mCurrentIntent); + activity.startInstrumentation(new ComponentName(activity, GodotInstrumentation.class), null, args); + } } public void alert(final String message, final String title) { - final Activity activity = this; + final Activity activity = getActivity(); runOnUiThread(new Runnable() { @Override public void run() { @@ -340,7 +348,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } public int getGLESVersionCode() { - ActivityManager am = (ActivityManager)this.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager am = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE); ConfigurationInfo deviceInfo = am.getDeviceConfigurationInfo(); return deviceInfo.reqGlEsVersion; } @@ -349,7 +357,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe protected String[] getCommandLine() { InputStream is; try { - is = getAssets().open("_cl_"); + is = getActivity().getAssets().open("_cl_"); byte[] len = new byte[4]; int r = is.read(len); if (r < 4) { @@ -426,11 +434,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe command_line = new_cmdline; } - io = new GodotIO(this); - io.unique_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID); + final Activity activity = getActivity(); + io = new GodotIO(activity); + io.unique_id = Secure.getString(activity.getContentResolver(), Secure.ANDROID_ID); GodotLib.io = io; - netUtils = new GodotNetUtils(this); - mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); + netUtils = new GodotNetUtils(activity); + mSensorManager = (SensorManager)activity.getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); mGravity = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY); @@ -440,7 +449,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); - GodotLib.initialize(this, getAssets(), use_apk_expansion); + GodotLib.initialize(activity, this, activity.getAssets(), use_apk_expansion); result_callback = null; @@ -454,151 +463,152 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); - Window window = getWindow(); + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle) { + final Activity activity = getActivity(); + Window window = activity.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); - mClipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); + mClipboard = (ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE); pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this); //check for apk expansion API - if (true) { - boolean md5mismatch = false; - command_line = getCommandLine(); - String main_pack_md5 = null; - String main_pack_key = null; - - List<String> new_args = new LinkedList<String>(); - - for (int i = 0; i < command_line.length; i++) { - boolean has_extra = i < command_line.length - 1; - if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) { - xrMode = XRMode.REGULAR; - } else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) { - xrMode = XRMode.OVR; - } else if (command_line[i].equals("--use_depth_32")) { - use_32_bits = true; - } else if (command_line[i].equals("--debug_opengl")) { - use_debug_opengl = true; - } else if (command_line[i].equals("--use_immersive")) { - use_immersive = true; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ - window.getDecorView().setSystemUiVisibility( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | - View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar - View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - - UiChangeListener(); - } - } else if (command_line[i].equals("--use_apk_expansion")) { - use_apk_expansion = true; - } else if (has_extra && command_line[i].equals("--apk_expansion_md5")) { - main_pack_md5 = command_line[i + 1]; - i++; - } else if (has_extra && command_line[i].equals("--apk_expansion_key")) { - main_pack_key = command_line[i + 1]; - SharedPreferences prefs = getSharedPreferences("app_data_keys", MODE_PRIVATE); - Editor editor = prefs.edit(); - editor.putString("store_public_key", main_pack_key); - - editor.apply(); - i++; - } else if (command_line[i].trim().length() != 0) { - new_args.add(command_line[i]); + boolean md5mismatch = false; + command_line = getCommandLine(); + String main_pack_md5 = null; + String main_pack_key = null; + + List<String> new_args = new LinkedList<String>(); + + for (int i = 0; i < command_line.length; i++) { + boolean has_extra = i < command_line.length - 1; + if (command_line[i].equals(XRMode.REGULAR.cmdLineArg)) { + xrMode = XRMode.REGULAR; + } else if (command_line[i].equals(XRMode.OVR.cmdLineArg)) { + xrMode = XRMode.OVR; + } else if (command_line[i].equals("--use_depth_32")) { + use_32_bits = true; + } else if (command_line[i].equals("--debug_opengl")) { + use_debug_opengl = true; + } else if (command_line[i].equals("--use_immersive")) { + use_immersive = true; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ + window.getDecorView().setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | + View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | // hide nav bar + View.SYSTEM_UI_FLAG_FULLSCREEN | // hide status bar + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + + UiChangeListener(); } + } else if (command_line[i].equals("--use_apk_expansion")) { + use_apk_expansion = true; + } else if (has_extra && command_line[i].equals("--apk_expansion_md5")) { + main_pack_md5 = command_line[i + 1]; + i++; + } else if (has_extra && command_line[i].equals("--apk_expansion_key")) { + main_pack_key = command_line[i + 1]; + SharedPreferences prefs = activity.getSharedPreferences("app_data_keys", + MODE_PRIVATE); + Editor editor = prefs.edit(); + editor.putString("store_public_key", main_pack_key); + + editor.apply(); + i++; + } else if (command_line[i].trim().length() != 0) { + new_args.add(command_line[i]); } + } - if (new_args.isEmpty()) { - command_line = null; - } else { - command_line = new_args.toArray(new String[new_args.size()]); + if (new_args.isEmpty()) { + command_line = null; + } else { + command_line = new_args.toArray(new String[new_args.size()]); + } + if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) { + //check that environment is ok! + if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + //show popup and die } - if (use_apk_expansion && main_pack_md5 != null && main_pack_key != null) { - //check that environment is ok! - if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - //show popup and die - } - // Build the full path to the app's expansion files - try { - expansion_pack_path = Helpers.getSaveFilePath(getApplicationContext()); - expansion_pack_path += "/main." + getPackageManager().getPackageInfo(getPackageName(), 0).versionCode + "." + this.getPackageName() + ".obb"; - } catch (Exception e) { - e.printStackTrace(); - } + // Build the full path to the app's expansion files + try { + expansion_pack_path = Helpers.getSaveFilePath(getContext()); + expansion_pack_path += "/main." + activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0).versionCode + "." + activity.getPackageName() + ".obb"; + } catch (Exception e) { + e.printStackTrace(); + } - File f = new File(expansion_pack_path); + File f = new File(expansion_pack_path); - boolean pack_valid = true; + boolean pack_valid = true; - if (!f.exists()) { - pack_valid = false; + if (!f.exists()) { + pack_valid = false; - } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) { - pack_valid = false; - try { - f.delete(); - } catch (Exception e) { - } + } else if (obbIsCorrupted(expansion_pack_path, main_pack_md5)) { + pack_valid = false; + try { + f.delete(); + } catch (Exception e) { } + } - if (!pack_valid) { - Intent notifierIntent = new Intent(this, this.getClass()); - notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - Intent.FLAG_ACTIVITY_CLEAR_TOP); + if (!pack_valid) { + Intent notifierIntent = new Intent(activity, activity.getClass()); + notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_ACTIVITY_CLEAR_TOP); - PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, - notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0, + notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); - int startResult; - try { - startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( - getApplicationContext(), - pendingIntent, + int startResult; + try { + startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( + getContext(), + pendingIntent, + GodotDownloaderService.class); + + if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { + // This is where you do set up to display the download + // progress (next step) + mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this, GodotDownloaderService.class); - if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { - // This is where you do set up to display the download - // progress (next step) - mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this, - GodotDownloaderService.class); - - setContentView(R.layout.downloading_expansion); - mPB = (ProgressBar)findViewById(R.id.progressBar); - mStatusText = (TextView)findViewById(R.id.statusText); - mProgressFraction = (TextView)findViewById(R.id.progressAsFraction); - mProgressPercent = (TextView)findViewById(R.id.progressAsPercentage); - mAverageSpeed = (TextView)findViewById(R.id.progressAverageSpeed); - mTimeRemaining = (TextView)findViewById(R.id.progressTimeRemaining); - mDashboard = findViewById(R.id.downloaderDashboard); - mCellMessage = findViewById(R.id.approveCellular); - mPauseButton = (Button)findViewById(R.id.pauseButton); - mWiFiSettingsButton = (Button)findViewById(R.id.wifiSettingsButton); - - return; - } - } catch (NameNotFoundException e) { - // TODO Auto-generated catch block + View downloadingExpansionView = + inflater.inflate(R.layout.downloading_expansion, container, false); + mPB = (ProgressBar)downloadingExpansionView.findViewById(R.id.progressBar); + mStatusText = (TextView)downloadingExpansionView.findViewById(R.id.statusText); + mProgressFraction = (TextView)downloadingExpansionView.findViewById(R.id.progressAsFraction); + mProgressPercent = (TextView)downloadingExpansionView.findViewById(R.id.progressAsPercentage); + mAverageSpeed = (TextView)downloadingExpansionView.findViewById(R.id.progressAverageSpeed); + mTimeRemaining = (TextView)downloadingExpansionView.findViewById(R.id.progressTimeRemaining); + mDashboard = downloadingExpansionView.findViewById(R.id.downloaderDashboard); + mCellMessage = downloadingExpansionView.findViewById(R.id.approveCellular); + mPauseButton = (Button)downloadingExpansionView.findViewById(R.id.pauseButton); + mWiFiSettingsButton = (Button)downloadingExpansionView.findViewById(R.id.wifiSettingsButton); + + return downloadingExpansionView; } + } catch (NameNotFoundException e) { + // TODO Auto-generated catch block } } } - mCurrentIntent = getIntent(); + mCurrentIntent = activity.getIntent(); initializeGodot(); + return containerLayout; } @Override - protected void onDestroy() { + public void onDestroy() { for (GodotPlugin plugin : pluginRegistry.getAllPlugins()) { plugin.onMainDestroy(); } - GodotLib.ondestroy(this); + GodotLib.ondestroy(); super.onDestroy(); @@ -608,13 +618,13 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } @Override - protected void onPause() { + public void onPause() { super.onPause(); activityResumed = false; if (!godot_initialized) { if (null != mDownloaderClientStub) { - mDownloaderClientStub.disconnect(this); + mDownloaderClientStub.disconnect(getActivity()); } return; } @@ -644,12 +654,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } @Override - protected void onResume() { + public void onResume() { super.onResume(); activityResumed = true; if (!godot_initialized) { if (null != mDownloaderClientStub) { - mDownloaderClientStub.connect(this); + mDownloaderClientStub.connect(getActivity()); } return; } @@ -662,7 +672,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe mSensorManager.registerListener(this, mGyroscope, SensorManager.SENSOR_DELAY_GAME); if (use_immersive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // check if the application runs on an android 4.4+ - Window window = getWindow(); + Window window = getActivity().getWindow(); window.getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | @@ -678,7 +688,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } public void UiChangeListener() { - final View decorView = getWindow().getDecorView(); + final View decorView = getActivity().getWindow().getDecorView(); decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { @@ -699,7 +709,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe @Override public void onSensorChanged(SensorEvent event) { - Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); + Display display = + ((WindowManager)getActivity().getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); int displayRotation = display.getRotation(); float[] adjustedValues = new float[3]; @@ -762,7 +773,6 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } */ - @Override public void onBackPressed() { boolean shouldQuit = true; @@ -793,6 +803,12 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } } + public final void runOnUiThread(@NonNull Runnable action) { + if (getActivity() != null) { + getActivity().runOnUiThread(action); + } + } + private void forceQuit() { System.exit(0); } @@ -895,18 +911,17 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe return true; } - @Override public boolean onKeyMultiple(final int inKeyCode, int repeatCount, KeyEvent event) { String s = event.getCharacters(); if (s == null || s.length() == 0) - return super.onKeyMultiple(inKeyCode, repeatCount, event); + return false; final char[] cc = s.toCharArray(); int cnt = 0; for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0) ; if (cnt == 0) - return super.onKeyMultiple(inKeyCode, repeatCount, event); + return false; mRenderView.queueOnRenderThread(new Runnable() { // This method will be called on the rendering thread: public void run() { @@ -924,15 +939,15 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe } public boolean requestPermission(String p_name) { - return PermissionsUtil.requestPermission(p_name, this); + return PermissionsUtil.requestPermission(p_name, getActivity()); } public boolean requestPermissions() { - return PermissionsUtil.requestManifestPermissions(this); + return PermissionsUtil.requestManifestPermissions(getActivity()); } public String[] getGrantedPermissions() { - return PermissionsUtil.getGrantedPermissions(this); + return PermissionsUtil.getGrantedPermissions(getActivity()); } /** diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java index 14dd893faa..4da2f31250 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java @@ -42,6 +42,7 @@ import org.godotengine.godot.xr.regular.RegularContextFactory; import org.godotengine.godot.xr.regular.RegularFallbackConfigChooser; import android.annotation.SuppressLint; +import android.content.Context; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; import android.view.GestureDetector; @@ -68,19 +69,20 @@ import android.view.SurfaceView; * bit depths). Failure to do so would result in an EGL_BAD_MATCH error. */ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView { - private final Godot activity; + private final Godot godot; private final GodotInputHandler inputHandler; private final GestureDetector detector; private final GodotRenderer godotRenderer; - public GodotGLRenderView(Godot activity, XRMode xrMode, boolean p_use_32_bits, boolean p_use_debug_opengl) { - super(activity); + public GodotGLRenderView(Context context, Godot godot, XRMode xrMode, boolean p_use_32_bits, + boolean p_use_debug_opengl) { + super(context); GLUtils.use_32 = p_use_32_bits; GLUtils.use_debug_opengl = p_use_debug_opengl; - this.activity = activity; + this.godot = godot; this.inputHandler = new GodotInputHandler(this); - this.detector = new GestureDetector(activity, new GodotGestureHandler(this)); + this.detector = new GestureDetector(context, new GodotGestureHandler(this)); this.godotRenderer = new GodotRenderer(); init(xrMode, false, 16, 0); } @@ -112,7 +114,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView @Override public void onBackPressed() { - activity.onBackPressed(); + godot.onBackPressed(); } @SuppressLint("ClickableViewAccessibility") @@ -120,7 +122,7 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); this.detector.onTouchEvent(event); - return activity.gotTouchEvent(event); + return godot.gotTouchEvent(event); } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java index 93f4786e83..4dd228e53b 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java @@ -32,6 +32,7 @@ package org.godotengine.godot; import org.godotengine.godot.input.*; +import android.app.Activity; import android.content.*; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -51,7 +52,7 @@ import java.util.Locale; public class GodotIO { AssetManager am; - Godot activity; + final Activity activity; GodotEditText edit; final int SCREEN_LANDSCAPE = 0; @@ -314,7 +315,7 @@ public class GodotIO { dirs.remove(id); } - GodotIO(Godot p_activity) { + GodotIO(Activity p_activity) { am = p_activity.getAssets(); activity = p_activity; //streams = new HashMap<Integer, AssetData>(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index 3693f36557..318e2816ff 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -50,13 +50,13 @@ public class GodotLib { /** * Invoked on the main thread to initialize Godot native layer. */ - public static native void initialize(Godot p_instance, Object p_asset_manager, boolean use_apk_expansion); + public static native void initialize(Activity activity, Godot p_instance, Object p_asset_manager, boolean use_apk_expansion); /** * Invoked on the main thread to clean up Godot native layer. - * @see Activity#onDestroy() + * @see androidx.fragment.app.Fragment#onDestroy() */ - public static native void ondestroy(Godot p_instance); + public static native void ondestroy(); /** * Invoked on the GL thread to complete setup for the Godot native layer logic. @@ -161,14 +161,14 @@ public class GodotLib { public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name); /** - * Invoked when the Android activity resumes. - * @see Activity#onResume() + * Invoked when the Android app resumes. + * @see androidx.fragment.app.Fragment#onResume() */ public static native void focusin(); /** - * Invoked when the Android activity pauses. - * @see Activity#onPause() + * Invoked when the Android app pauses. + * @see androidx.fragment.app.Fragment#onPause() */ public static native void focusout(); diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java index e9872b58ff..aace593bae 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java @@ -36,23 +36,24 @@ import org.godotengine.godot.vulkan.VkRenderer; import org.godotengine.godot.vulkan.VkSurfaceView; import android.annotation.SuppressLint; +import android.content.Context; import android.view.GestureDetector; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.SurfaceView; public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderView { - private final Godot mActivity; + private final Godot godot; private final GodotInputHandler mInputHandler; private final GestureDetector mGestureDetector; private final VkRenderer mRenderer; - public GodotVulkanRenderView(Godot activity) { - super(activity); + public GodotVulkanRenderView(Context context, Godot godot) { + super(context); - mActivity = activity; + this.godot = godot; mInputHandler = new GodotInputHandler(this); - mGestureDetector = new GestureDetector(mActivity, new GodotGestureHandler(this)); + mGestureDetector = new GestureDetector(context, new GodotGestureHandler(this)); mRenderer = new VkRenderer(); setFocusableInTouchMode(true); @@ -86,7 +87,7 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV @Override public void onBackPressed() { - mActivity.onBackPressed(); + godot.onBackPressed(); } @SuppressLint("ClickableViewAccessibility") @@ -94,7 +95,7 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); mGestureDetector.onTouchEvent(event); - return mActivity.gotTouchEvent(event); + return godot.gotTouchEvent(event); } @Override diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java index ce85880fa3..93c204935c 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPlugin.java @@ -98,7 +98,7 @@ public abstract class GodotPlugin { */ @Nullable protected Activity getActivity() { - return godot; + return godot.getActivity(); } /** diff --git a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java index 12d2ed09fb..1c2d1a6563 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java +++ b/platform/android/java/lib/src/org/godotengine/godot/plugin/GodotPluginRegistry.java @@ -32,6 +32,7 @@ package org.godotengine.godot.plugin; import org.godotengine.godot.Godot; +import android.app.Activity; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Bundle; @@ -121,9 +122,11 @@ public final class GodotPluginRegistry { private void loadPlugins(Godot godot) { try { - ApplicationInfo appInfo = godot + final Activity activity = godot.getActivity(); + ApplicationInfo appInfo = activity .getPackageManager() - .getApplicationInfo(godot.getPackageName(), PackageManager.GET_META_DATA); + .getApplicationInfo(activity.getPackageName(), + PackageManager.GET_META_DATA); Bundle metaData = appInfo.metaData; if (metaData == null || metaData.isEmpty()) { return; diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java index 0832a9b965..c89118ad55 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/GodotNetUtils.java @@ -30,8 +30,7 @@ package org.godotengine.godot.utils; -import org.godotengine.godot.Godot; - +import android.app.Activity; import android.content.Context; import android.net.wifi.WifiManager; import android.util.Log; @@ -45,7 +44,7 @@ public class GodotNetUtils { /* A single, reference counted, multicast lock, or null if permission CHANGE_WIFI_MULTICAST_STATE is missing */ private WifiManager.MulticastLock multicastLock; - public GodotNetUtils(Godot p_activity) { + public GodotNetUtils(Activity p_activity) { if (PermissionsUtil.hasManifestPermission(p_activity, "android.permission.CHANGE_WIFI_MULTICAST_STATE")) { WifiManager wifi = (WifiManager)p_activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE); multicastLock = wifi.createMulticastLock("GodotMulticastLock"); diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java index 6837e4f147..7104baf86e 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java +++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java @@ -30,9 +30,8 @@ package org.godotengine.godot.utils; -import org.godotengine.godot.Godot; - import android.Manifest; +import android.app.Activity; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PermissionInfo; @@ -65,7 +64,7 @@ public final class PermissionsUtil { * @param activity the caller activity for this method. * @return true/false. "true" if permission was granted otherwise returns "false". */ - public static boolean requestPermission(String name, Godot activity) { + public static boolean requestPermission(String name, Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { // Not necessary, asked on install already return true; @@ -93,7 +92,7 @@ public final class PermissionsUtil { * @param activity the caller activity for this method. * @return true/false. "true" if all permissions were granted otherwise returns "false". */ - public static boolean requestManifestPermissions(Godot activity) { + public static boolean requestManifestPermissions(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return true; } @@ -138,7 +137,7 @@ public final class PermissionsUtil { * @param activity the caller activity for this method. * @return granted permissions list */ - public static String[] getGrantedPermissions(Godot activity) { + public static String[] getGrantedPermissions(Activity activity) { String[] manifestPermissions; try { manifestPermissions = getManifestPermissions(activity); @@ -172,7 +171,7 @@ public final class PermissionsUtil { * @param permission the permession to look for in the manifest file. * @return "true" if the permission is in the manifest file of the activity, "false" otherwise. */ - public static boolean hasManifestPermission(Godot activity, String permission) { + public static boolean hasManifestPermission(Activity activity, String permission) { try { for (String p : getManifestPermissions(activity)) { if (permission.equals(p)) @@ -190,7 +189,7 @@ public final class PermissionsUtil { * @return manifest permissions list * @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found. */ - private static String[] getManifestPermissions(Godot activity) throws PackageManager.NameNotFoundException { + private static String[] getManifestPermissions(Activity activity) throws PackageManager.NameNotFoundException { PackageManager packageManager = activity.getPackageManager(); PackageInfo packageInfo = packageManager.getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS); if (packageInfo.requestedPermissions == null) @@ -205,7 +204,7 @@ public final class PermissionsUtil { * @return permission info object * @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found. */ - private static PermissionInfo getPermissionInfo(Godot activity, String permission) throws PackageManager.NameNotFoundException { + private static PermissionInfo getPermissionInfo(Activity activity, String permission) throws PackageManager.NameNotFoundException { PackageManager packageManager = activity.getPackageManager(); return packageManager.getPermissionInfo(permission, 0); } diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index 39de3cb642..9b44ac4b41 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -1150,7 +1150,7 @@ JavaClassWrapper::JavaClassWrapper(jobject p_activity) { JNIEnv *env = ThreadAndroid::get_env(); - jclass activityClass = env->FindClass("org/godotengine/godot/Godot"); + jclass activityClass = env->FindClass("android/app/Activity"); jmethodID getClassLoader = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); classLoader = env->CallObjectMethod(p_activity, getClassLoader); classLoader = (jclass)env->NewGlobalRef(classLoader); diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 8667727b1d..4610b94363 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -77,14 +77,14 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei } } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion) { initialized = true; JavaVM *jvm; env->GetJavaVM(&jvm); // create our wrapper classes - godot_java = new GodotJavaWrapper(env, activity); // our activity is our godot instance is our activity.. + godot_java = new GodotJavaWrapper(env, activity, godot_instance); godot_io_java = new GodotIOJavaWrapper(env, godot_java->get_member_object("io", "Lorg/godotengine/godot/GodotIO;", env)); ThreadAndroid::make_default(jvm); @@ -109,7 +109,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en godot_java->on_video_init(env); } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz) { // lets cleanup if (godot_io_java) { delete godot_io_java; @@ -457,7 +457,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNI return; if (os_android->get_main_loop()) { - os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_RESUMED); + os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_RESUMED); } } @@ -466,7 +466,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIE return; if (os_android->get_main_loop()) { - os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APP_PAUSED); + os_android->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_PAUSED); } } } diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index e8be7be0d0..07584518e5 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -37,8 +37,8 @@ // These functions can be called from within JAVA and are the means by which our JAVA implementation calls back into our C++ code. // See java/src/org/godotengine/godot/GodotLib.java for the JAVA side of this (yes that's why we have the long names) extern "C" { -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion); -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz, jobject activity); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject activity, jobject godot_instance, jobject p_asset_manager, jboolean p_use_apk_expansion); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jobject p_surface, jint p_width, jint p_height); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jclass clazz, jobject p_surface, jboolean p_32_bits); diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp index 8ef99dfab0..cff591d903 100644 --- a/platform/android/java_godot_wrapper.cpp +++ b/platform/android/java_godot_wrapper.cpp @@ -37,36 +37,47 @@ // TODO we could probably create a base class for this... -GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) { +GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance) { godot_instance = p_env->NewGlobalRef(p_godot_instance); + activity = p_env->NewGlobalRef(p_activity); // get info about our Godot class so we can get pointers and stuff... - cls = p_env->FindClass("org/godotengine/godot/Godot"); - if (cls) { - cls = (jclass)p_env->NewGlobalRef(cls); + godot_class = p_env->FindClass("org/godotengine/godot/Godot"); + if (godot_class) { + godot_class = (jclass)p_env->NewGlobalRef(godot_class); + } else { + // this is a pretty serious fail.. bail... pointers will stay 0 + return; + } + activity_class = p_env->FindClass("android/app/Activity"); + if (activity_class) { + activity_class = (jclass)p_env->NewGlobalRef(activity_class); } else { // this is a pretty serious fail.. bail... pointers will stay 0 return; } - // get some method pointers... - _on_video_init = p_env->GetMethodID(cls, "onVideoInit", "()V"); - _restart = p_env->GetMethodID(cls, "restart", "()V"); - _finish = p_env->GetMethodID(cls, "forceQuit", "()V"); - _set_keep_screen_on = p_env->GetMethodID(cls, "setKeepScreenOn", "(Z)V"); - _alert = p_env->GetMethodID(cls, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); - _get_GLES_version_code = p_env->GetMethodID(cls, "getGLESVersionCode", "()I"); - _get_clipboard = p_env->GetMethodID(cls, "getClipboard", "()Ljava/lang/String;"); - _set_clipboard = p_env->GetMethodID(cls, "setClipboard", "(Ljava/lang/String;)V"); - _request_permission = p_env->GetMethodID(cls, "requestPermission", "(Ljava/lang/String;)Z"); - _request_permissions = p_env->GetMethodID(cls, "requestPermissions", "()Z"); - _get_granted_permissions = p_env->GetMethodID(cls, "getGrantedPermissions", "()[Ljava/lang/String;"); - _init_input_devices = p_env->GetMethodID(cls, "initInputDevices", "()V"); - _get_surface = p_env->GetMethodID(cls, "getSurface", "()Landroid/view/Surface;"); - _is_activity_resumed = p_env->GetMethodID(cls, "isActivityResumed", "()Z"); - _vibrate = p_env->GetMethodID(cls, "vibrate", "(I)V"); - _get_input_fallback_mapping = p_env->GetMethodID(cls, "getInputFallbackMapping", "()Ljava/lang/String;"); - _on_godot_main_loop_started = p_env->GetMethodID(cls, "onGodotMainLoopStarted", "()V"); + // get some Godot method pointers... + _on_video_init = p_env->GetMethodID(godot_class, "onVideoInit", "()V"); + _restart = p_env->GetMethodID(godot_class, "restart", "()V"); + _finish = p_env->GetMethodID(godot_class, "forceQuit", "()V"); + _set_keep_screen_on = p_env->GetMethodID(godot_class, "setKeepScreenOn", "(Z)V"); + _alert = p_env->GetMethodID(godot_class, "alert", "(Ljava/lang/String;Ljava/lang/String;)V"); + _get_GLES_version_code = p_env->GetMethodID(godot_class, "getGLESVersionCode", "()I"); + _get_clipboard = p_env->GetMethodID(godot_class, "getClipboard", "()Ljava/lang/String;"); + _set_clipboard = p_env->GetMethodID(godot_class, "setClipboard", "(Ljava/lang/String;)V"); + _request_permission = p_env->GetMethodID(godot_class, "requestPermission", "(Ljava/lang/String;)Z"); + _request_permissions = p_env->GetMethodID(godot_class, "requestPermissions", "()Z"); + _get_granted_permissions = p_env->GetMethodID(godot_class, "getGrantedPermissions", "()[Ljava/lang/String;"); + _init_input_devices = p_env->GetMethodID(godot_class, "initInputDevices", "()V"); + _get_surface = p_env->GetMethodID(godot_class, "getSurface", "()Landroid/view/Surface;"); + _is_activity_resumed = p_env->GetMethodID(godot_class, "isActivityResumed", "()Z"); + _vibrate = p_env->GetMethodID(godot_class, "vibrate", "(I)V"); + _get_input_fallback_mapping = p_env->GetMethodID(godot_class, "getInputFallbackMapping", "()Ljava/lang/String;"); + _on_godot_main_loop_started = p_env->GetMethodID(godot_class, "onGodotMainLoopStarted", "()V"); + + // get some Activity method pointers... + _get_class_loader = p_env->GetMethodID(activity_class, "getClassLoader", "()Ljava/lang/ClassLoader;"); } GodotJavaWrapper::~GodotJavaWrapper() { @@ -74,27 +85,25 @@ GodotJavaWrapper::~GodotJavaWrapper() { } jobject GodotJavaWrapper::get_activity() { - // our godot instance is our activity - return godot_instance; + return activity; } jobject GodotJavaWrapper::get_member_object(const char *p_name, const char *p_class, JNIEnv *p_env) { - if (cls) { + if (godot_class) { if (p_env == nullptr) p_env = ThreadAndroid::get_env(); - jfieldID fid = p_env->GetStaticFieldID(cls, p_name, p_class); - return p_env->GetStaticObjectField(cls, fid); + jfieldID fid = p_env->GetStaticFieldID(godot_class, p_name, p_class); + return p_env->GetStaticObjectField(godot_class, fid); } else { return nullptr; } } jobject GodotJavaWrapper::get_class_loader() { - if (cls) { + if (_get_class_loader) { JNIEnv *env = ThreadAndroid::get_env(); - jmethodID getClassLoader = env->GetMethodID(cls, "getClassLoader", "()Ljava/lang/ClassLoader;"); - return env->CallObjectMethod(godot_instance, getClassLoader); + return env->CallObjectMethod(godot_instance, _get_class_loader); } else { return nullptr; } diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h index 89d6b6db46..e0c3809a64 100644 --- a/platform/android/java_godot_wrapper.h +++ b/platform/android/java_godot_wrapper.h @@ -43,7 +43,9 @@ class GodotJavaWrapper { private: jobject godot_instance; - jclass cls; + jobject activity; + jclass godot_class; + jclass activity_class; jmethodID _on_video_init = 0; jmethodID _restart = 0; @@ -62,9 +64,10 @@ private: jmethodID _vibrate = 0; jmethodID _get_input_fallback_mapping = 0; jmethodID _on_godot_main_loop_started = 0; + jmethodID _get_class_loader = 0; public: - GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance); + GodotJavaWrapper(JNIEnv *p_env, jobject p_activity, jobject p_godot_instance); ~GodotJavaWrapper(); jobject get_activity(); diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 194e71c9de..4393a4ae9f 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -793,17 +793,33 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese String pbx_frameworks_refs; String pbx_resources_build; String pbx_resources_refs; + String pbx_embeded_frameworks; const String file_info_format = String("$build_id = {isa = PBXBuildFile; fileRef = $ref_id; };\n") + "$ref_id = {isa = PBXFileReference; lastKnownFileType = $file_type; name = \"$name\"; path = \"$file_path\"; sourceTree = \"<group>\"; };\n"; + for (int i = 0; i < p_additional_assets.size(); ++i) { + String additional_asset_info_format = file_info_format; + String build_id = (++current_id).str(); String ref_id = (++current_id).str(); + String framework_id = ""; + const IOSExportAsset &asset = p_additional_assets[i]; String type; if (asset.exported_path.ends_with(".framework")) { + additional_asset_info_format += "$framework_id = {isa = PBXBuildFile; fileRef = $ref_id; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n"; + framework_id = (++current_id).str(); + pbx_embeded_frameworks += framework_id + ",\n"; + type = "wrapper.framework"; + } else if (asset.exported_path.ends_with(".xcframework")) { + additional_asset_info_format += "$framework_id = {isa = PBXBuildFile; fileRef = $ref_id; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n"; + framework_id = (++current_id).str(); + pbx_embeded_frameworks += framework_id + ",\n"; + + type = "wrapper.xcframework"; } else if (asset.exported_path.ends_with(".dylib")) { type = "compiled.mach-o.dylib"; } else if (asset.exported_path.ends_with(".a")) { @@ -828,7 +844,10 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese format_dict["name"] = asset.exported_path.get_file(); format_dict["file_path"] = asset.exported_path; format_dict["file_type"] = type; - pbx_files += file_info_format.format(format_dict, "$_"); + if (framework_id.length() > 0) { + format_dict["framework_id"] = framework_id; + } + pbx_files += additional_asset_info_format.format(format_dict, "$_"); } // Note, frameworks like gamekit are always included in our project.pbxprof file @@ -862,6 +881,7 @@ void EditorExportPlatformIOS::_add_assets_to_project(const Ref<EditorExportPrese str = str.replace("$additional_pbx_frameworks_refs", pbx_frameworks_refs); str = str.replace("$additional_pbx_resources_build", pbx_resources_build); str = str.replace("$additional_pbx_resources_refs", pbx_resources_refs); + str = str.replace("$pbx_embeded_frameworks", pbx_embeded_frameworks); CharString cs = str.utf8(); p_project_data.resize(cs.size() - 1); @@ -892,8 +912,39 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir memdelete(filesystem_da); return ERR_FILE_NOT_FOUND; } - String additional_dir = p_is_framework && asset.ends_with(".dylib") ? "/dylibs/" : "/"; - String destination_dir = p_out_dir + additional_dir + asset.get_base_dir().replace("res://", ""); + + String base_dir = asset.get_base_dir().replace("res://", ""); + String destination_dir; + String destination; + String asset_path; + bool create_framework = false; + + if (p_is_framework && asset.ends_with(".dylib")) { + // For iOS we need to turn .dylib into .framework + // to be able to send application to AppStore + destination_dir = p_out_dir.plus_file("dylibs").plus_file(base_dir); + + String file_name = asset.get_basename().get_file(); + String framework_name = file_name + ".framework"; + + destination_dir = destination_dir.plus_file(framework_name); + destination = destination_dir.plus_file(file_name); + asset_path = destination_dir; + create_framework = true; + } else if (p_is_framework && (asset.ends_with(".framework") || asset.ends_with(".xcframework"))) { + destination_dir = p_out_dir.plus_file("dylibs").plus_file(base_dir); + + String file_name = asset.get_file(); + destination = destination_dir.plus_file(file_name); + asset_path = destination; + } else { + destination_dir = p_out_dir.plus_file(base_dir); + + String file_name = asset.get_file(); + destination = destination_dir.plus_file(file_name); + asset_path = destination; + } + if (!filesystem_da->dir_exists(destination_dir)) { Error make_dir_err = filesystem_da->make_dir_recursive(destination_dir); if (make_dir_err) { @@ -903,15 +954,66 @@ Error EditorExportPlatformIOS::_export_additional_assets(const String &p_out_dir } } - String destination = destination_dir.plus_file(asset.get_file()); Error err = dir_exists ? da->copy_dir(asset, destination) : da->copy(asset, destination); memdelete(da); if (err) { memdelete(filesystem_da); return err; } - IOSExportAsset exported_asset = { destination, p_is_framework }; + IOSExportAsset exported_asset = { asset_path, p_is_framework }; r_exported_assets.push_back(exported_asset); + + if (create_framework) { + String file_name = asset.get_basename().get_file(); + String framework_name = file_name + ".framework"; + + // Performing `install_name_tool -id @rpath/{name}.framework/{name} ./{name}` on dylib + { + List<String> install_name_args; + install_name_args.push_back("-id"); + install_name_args.push_back(String("@rpath").plus_file(framework_name).plus_file(file_name)); + install_name_args.push_back(destination); + + OS::get_singleton()->execute("install_name_tool", install_name_args, true); + } + + // Creating Info.plist + { + String info_plist_format = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + "<plist version=\"1.0\">\n" + "<dict>\n" + "<key>CFBundleShortVersionString</key>\n" + "<string>1.0</string>\n" + "<key>CFBundleIdentifier</key>\n" + "<string>com.gdnative.framework.$name</string>\n" + "<key>CFBundleName</key>\n" + "<string>$name</string>\n" + "<key>CFBundleExecutable</key>\n" + "<string>$name</string>\n" + "<key>DTPlatformName</key>\n" + "<string>iphoneos</string>\n" + "<key>CFBundleInfoDictionaryVersion</key>\n" + "<string>6.0</string>\n" + "<key>CFBundleVersion</key>\n" + "<string>1</string>\n" + "<key>CFBundlePackageType</key>\n" + "<string>FMWK</string>\n" + "<key>MinimumOSVersion</key>\n" + "<string>10.0</string>\n" + "</dict>\n" + "</plist>"; + + String info_plist = info_plist_format.replace("$name", file_name); + + FileAccess *f = FileAccess::open(asset_path.plus_file("Info.plist"), FileAccess::WRITE); + if (f) { + f->store_string(info_plist); + f->close(); + memdelete(f); + } + } + } } } memdelete(filesystem_da); diff --git a/platform/javascript/audio_driver_javascript.cpp b/platform/javascript/audio_driver_javascript.cpp index b8914414e6..9604914b2c 100644 --- a/platform/javascript/audio_driver_javascript.cpp +++ b/platform/javascript/audio_driver_javascript.cpp @@ -36,6 +36,15 @@ AudioDriverJavaScript *AudioDriverJavaScript::singleton = nullptr; +bool AudioDriverJavaScript::is_available() { + return EM_ASM_INT({ + if (!(window.AudioContext || window.webkitAudioContext)) { + return 0; + } + return 1; + }) != 0; +} + const char *AudioDriverJavaScript::get_name() const { return "JavaScript"; } @@ -207,12 +216,14 @@ void AudioDriverJavaScript::finish_async() { /* clang-format off */ EM_ASM({ - var ref = Module.IDHandler.get($0); + const id = $0; + var ref = Module.IDHandler.get(id); Module.async_finish.push(new Promise(function(accept, reject) { if (!ref) { - console.log("Ref not found!", $0, Module.IDHandler); + console.log("Ref not found!", id, Module.IDHandler); setTimeout(accept, 0); } else { + Module.IDHandler.remove(id); const context = ref['context']; // Disconnect script and input. ref['script'].disconnect(); @@ -226,7 +237,6 @@ void AudioDriverJavaScript::finish_async() { }); } })); - Module.IDHandler.remove($0); }, id); /* clang-format on */ } @@ -293,9 +303,5 @@ Error AudioDriverJavaScript::capture_stop() { } AudioDriverJavaScript::AudioDriverJavaScript() { - _driver_id = 0; - internal_buffer = nullptr; - buffer_length = 0; - singleton = this; } diff --git a/platform/javascript/audio_driver_javascript.h b/platform/javascript/audio_driver_javascript.h index 9b26be001e..f029a91db0 100644 --- a/platform/javascript/audio_driver_javascript.h +++ b/platform/javascript/audio_driver_javascript.h @@ -34,12 +34,13 @@ #include "servers/audio_server.h" class AudioDriverJavaScript : public AudioDriver { - float *internal_buffer; + float *internal_buffer = nullptr; - int _driver_id; - int buffer_length; + int _driver_id = 0; + int buffer_length = 0; public: + static bool is_available(); void mix_to_js(); void process_capture(float sample); diff --git a/platform/javascript/display_server_javascript.cpp b/platform/javascript/display_server_javascript.cpp index 0312efb377..2f0a2faa83 100644 --- a/platform/javascript/display_server_javascript.cpp +++ b/platform/javascript/display_server_javascript.cpp @@ -44,18 +44,15 @@ #define DOM_BUTTON_XBUTTON1 3 #define DOM_BUTTON_XBUTTON2 4 +char DisplayServerJavaScript::canvas_id[256] = { 0 }; +static bool cursor_inside_canvas = true; + DisplayServerJavaScript *DisplayServerJavaScript::get_singleton() { return static_cast<DisplayServerJavaScript *>(DisplayServer::get_singleton()); } // Window (canvas) -extern "C" EMSCRIPTEN_KEEPALIVE void _set_canvas_id(uint8_t *p_data, int p_data_size) { - DisplayServerJavaScript *display = DisplayServerJavaScript::get_singleton(); - display->canvas_id.parse_utf8((const char *)p_data, p_data_size); - display->canvas_id = "#" + display->canvas_id; -} - -static void focus_canvas() { +void DisplayServerJavaScript::focus_canvas() { /* clang-format off */ EM_ASM( Module['canvas'].focus(); @@ -63,7 +60,7 @@ static void focus_canvas() { /* clang-format on */ } -static bool is_canvas_focused() { +bool DisplayServerJavaScript::is_canvas_focused() { /* clang-format off */ return EM_ASM_INT_V( return document.activeElement == Module['canvas']; @@ -71,8 +68,21 @@ static bool is_canvas_focused() { /* clang-format on */ } -static Point2 compute_position_in_canvas(int x, int y) { - DisplayServerJavaScript *display = DisplayServerJavaScript::get_singleton(); +bool DisplayServerJavaScript::check_size_force_redraw() { + int canvas_width; + int canvas_height; + emscripten_get_canvas_element_size(DisplayServerJavaScript::canvas_id, &canvas_width, &canvas_height); + if (last_width != canvas_width || last_height != canvas_height) { + last_width = canvas_width; + last_height = canvas_height; + // Update the framebuffer size and for redraw. + emscripten_set_canvas_element_size(DisplayServerJavaScript::canvas_id, canvas_width, canvas_height); + return true; + } + return false; +} + +Point2 DisplayServerJavaScript::compute_position_in_canvas(int p_x, int p_y) { int canvas_x = EM_ASM_INT({ return Module['canvas'].getBoundingClientRect().x; }); @@ -81,23 +91,22 @@ static Point2 compute_position_in_canvas(int x, int y) { }); int canvas_width; int canvas_height; - emscripten_get_canvas_element_size(display->canvas_id.utf8().get_data(), &canvas_width, &canvas_height); + emscripten_get_canvas_element_size(canvas_id, &canvas_width, &canvas_height); double element_width; double element_height; - emscripten_get_element_css_size(display->canvas_id.utf8().get_data(), &element_width, &element_height); + emscripten_get_element_css_size(canvas_id, &element_width, &element_height); - return Point2((int)(canvas_width / element_width * (x - canvas_x)), - (int)(canvas_height / element_height * (y - canvas_y))); + return Point2((int)(canvas_width / element_width * (p_x - canvas_x)), + (int)(canvas_height / element_height * (p_y - canvas_y))); } -static bool cursor_inside_canvas = true; - EM_BOOL DisplayServerJavaScript::fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data) { DisplayServerJavaScript *display = get_singleton(); // Empty ID is canvas. String target_id = String::utf8(p_event->id); - if (target_id.empty() || "#" + target_id == display->canvas_id) { + String canvas_str_id = String::utf8(canvas_id); + if (target_id.empty() || target_id == canvas_str_id) { // This event property is the only reliable data on // browser fullscreen state. if (p_event->isFullscreen) { @@ -131,14 +140,14 @@ extern "C" EMSCRIPTEN_KEEPALIVE void _drop_files_callback(char *p_filev[], int p // Keys template <typename T> -static void dom2godot_mod(T *emscripten_event_ptr, Ref<InputEventWithModifiers> godot_event) { +void DisplayServerJavaScript::dom2godot_mod(T *emscripten_event_ptr, Ref<InputEventWithModifiers> godot_event) { godot_event->set_shift(emscripten_event_ptr->shiftKey); godot_event->set_alt(emscripten_event_ptr->altKey); godot_event->set_control(emscripten_event_ptr->ctrlKey); godot_event->set_metakey(emscripten_event_ptr->metaKey); } -static Ref<InputEventKey> setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) { +Ref<InputEventKey> DisplayServerJavaScript::setup_key_event(const EmscriptenKeyboardEvent *emscripten_event) { Ref<InputEventKey> ev; ev.instance(); ev->set_echo(emscripten_event->repeat); @@ -289,7 +298,7 @@ EM_BOOL DisplayServerJavaScript::mousemove_callback(int p_event_type, const Emsc } // Cursor -static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape) { +const char *DisplayServerJavaScript::godot2dom_cursor(DisplayServer::CursorShape p_shape) { switch (p_shape) { case DisplayServer::CURSOR_ARROW: return "auto"; @@ -330,7 +339,7 @@ static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape) { } } -static void set_css_cursor(const char *p_cursor) { +void DisplayServerJavaScript::set_css_cursor(const char *p_cursor) { /* clang-format off */ EM_ASM_({ Module['canvas'].style.cursor = UTF8ToString($0); @@ -338,7 +347,7 @@ static void set_css_cursor(const char *p_cursor) { /* clang-format on */ } -static bool is_css_cursor_hidden() { +bool DisplayServerJavaScript::is_css_cursor_hidden() const { /* clang-format off */ return EM_ASM_INT({ return Module['canvas'].style.cursor === 'none'; @@ -820,23 +829,6 @@ DisplayServer *DisplayServerJavaScript::create_func(const String &p_rendering_dr } DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { - /* clang-format off */ - EM_ASM({ - const canvas = Module['canvas']; - var enc = new TextEncoder("utf-8"); - var buffer = new Uint8Array(enc.encode(canvas.id)); - var len = buffer.byteLength; - var out = _malloc(len); - HEAPU8.set(buffer, out); - ccall("_set_canvas_id", - "void", - ["number", "number"], - [out, len] - ); - _free(out); - }); - /* clang-format on */ - RasterizerDummy::make_current(); // TODO GLES2 in Godot 4.0... or webgpu? #if 0 EmscriptenWebGLContextAttributes attributes; @@ -859,7 +851,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive gl_initialization_error = true; } - EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(canvas_id.utf8().get_data(), &attributes); + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(canvas_id, &attributes); if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) { gl_initialization_error = true; } @@ -881,7 +873,6 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive } EMSCRIPTEN_RESULT result; - CharString id = canvas_id.utf8(); #define EM_CHECK(ev) \ if (result != EMSCRIPTEN_RESULT_SUCCESS) \ ERR_PRINT("Error while setting " #ev " callback: Code " + itos(result)); @@ -895,16 +886,16 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive // JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM // is used below. SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mousemove, mousemove_callback) - SET_EM_CALLBACK(id.get_data(), mousedown, mouse_button_callback) + SET_EM_CALLBACK(canvas_id, mousedown, mouse_button_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback) - SET_EM_CALLBACK(id.get_data(), wheel, wheel_callback) - SET_EM_CALLBACK(id.get_data(), touchstart, touch_press_callback) - SET_EM_CALLBACK(id.get_data(), touchmove, touchmove_callback) - SET_EM_CALLBACK(id.get_data(), touchend, touch_press_callback) - SET_EM_CALLBACK(id.get_data(), touchcancel, touch_press_callback) - SET_EM_CALLBACK(id.get_data(), keydown, keydown_callback) - SET_EM_CALLBACK(id.get_data(), keypress, keypress_callback) - SET_EM_CALLBACK(id.get_data(), keyup, keyup_callback) + SET_EM_CALLBACK(canvas_id, wheel, wheel_callback) + SET_EM_CALLBACK(canvas_id, touchstart, touch_press_callback) + SET_EM_CALLBACK(canvas_id, touchmove, touchmove_callback) + SET_EM_CALLBACK(canvas_id, touchend, touch_press_callback) + SET_EM_CALLBACK(canvas_id, touchcancel, touch_press_callback) + SET_EM_CALLBACK(canvas_id, keydown, keydown_callback) + SET_EM_CALLBACK(canvas_id, keypress, keypress_callback) + SET_EM_CALLBACK(canvas_id, keyup, keyup_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, fullscreenchange, fullscreen_change_callback) SET_EM_CALLBACK_NOTARGET(gamepadconnected, gamepad_change_callback) SET_EM_CALLBACK_NOTARGET(gamepaddisconnected, gamepad_change_callback) @@ -1012,7 +1003,7 @@ Size2i DisplayServerJavaScript::screen_get_size(int p_screen) const { Rect2i DisplayServerJavaScript::screen_get_usable_rect(int p_screen) const { int canvas[2]; - emscripten_get_canvas_element_size(canvas_id.utf8().get_data(), canvas, canvas + 1); + emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1); return Rect2i(0, 0, canvas[0], canvas[1]); } @@ -1103,12 +1094,14 @@ Size2i DisplayServerJavaScript::window_get_min_size(WindowID p_window) const { } void DisplayServerJavaScript::window_set_size(const Size2i p_size, WindowID p_window) { - emscripten_set_canvas_element_size(canvas_id.utf8().get_data(), p_size.x, p_size.y); + last_width = p_size.x; + last_height = p_size.y; + emscripten_set_canvas_element_size(canvas_id, p_size.x, p_size.y); } Size2i DisplayServerJavaScript::window_get_size(WindowID p_window) const { int canvas[2]; - emscripten_get_canvas_element_size(canvas_id.utf8().get_data(), canvas, canvas + 1); + emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1); return Size2(canvas[0], canvas[1]); } @@ -1134,7 +1127,7 @@ void DisplayServerJavaScript::window_set_mode(WindowMode p_mode, WindowID p_wind strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.canvasResizedCallback = nullptr; - EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(canvas_id.utf8().get_data(), false, &strategy); + EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(canvas_id, false, &strategy); ERR_FAIL_COND_MSG(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); ERR_FAIL_COND_MSG(result != EMSCRIPTEN_RESULT_SUCCESS, "Enabling fullscreen is only possible from an input callback for the HTML5 platform."); } break; diff --git a/platform/javascript/display_server_javascript.h b/platform/javascript/display_server_javascript.h index 9860ecdf98..b149665d67 100644 --- a/platform/javascript/display_server_javascript.h +++ b/platform/javascript/display_server_javascript.h @@ -53,6 +53,21 @@ class DisplayServerJavaScript : public DisplayServer { double last_click_ms = 0; int last_click_button_index = -1; + int last_width = 0; + int last_height = 0; + + // utilities + static Point2 compute_position_in_canvas(int p_x, int p_y); + static void focus_canvas(); + static bool is_canvas_focused(); + template <typename T> + static void dom2godot_mod(T *emscripten_event_ptr, Ref<InputEventWithModifiers> godot_event); + static Ref<InputEventKey> setup_key_event(const EmscriptenKeyboardEvent *emscripten_event); + static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape); + static void set_css_cursor(const char *p_cursor); + bool is_css_cursor_hidden() const; + + // events static EM_BOOL fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data); static EM_BOOL keydown_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data); @@ -81,17 +96,20 @@ protected: public: // Override return type to make writing static callbacks less tedious. static DisplayServerJavaScript *get_singleton(); + static char canvas_id[256]; WindowMode window_mode = WINDOW_MODE_WINDOWED; String clipboard; - String canvas_id; Callable window_event_callback; Callable input_event_callback; Callable input_text_callback; Callable drop_files_callback; + // utilities + bool check_size_force_redraw(); + // from DisplayServer virtual void alert(const String &p_alert, const String &p_title = "ALERT!"); virtual bool has_feature(Feature p_feature) const; diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index fd61c46e63..99672745e7 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -30,11 +30,13 @@ #include "core/io/resource_loader.h" #include "main/main.h" -#include "os_javascript.h" +#include "platform/javascript/display_server_javascript.h" +#include "platform/javascript/os_javascript.h" #include <emscripten/emscripten.h> static OS_JavaScript *os = nullptr; +static uint64_t target_ticks = 0; void exit_callback() { emscripten_cancel_main_loop(); // After this, we can exit! @@ -46,12 +48,32 @@ void exit_callback() { } void main_loop_callback() { + uint64_t current_ticks = os->get_ticks_usec(); + + bool force_draw = DisplayServerJavaScript::get_singleton()->check_size_force_redraw(); + if (force_draw) { + Main::force_redraw(); + } else if (current_ticks < target_ticks) { + return; // Skip frame. + } + + int target_fps = Engine::get_singleton()->get_target_fps(); + if (target_fps > 0) { + target_ticks += (uint64_t)(1000000 / target_fps); + } if (os->main_loop_iterate()) { emscripten_cancel_main_loop(); // Cancel current loop and wait for finalize_async. + /* clang-format off */ EM_ASM({ // This will contain the list of operations that need to complete before cleanup. - Module.async_finish = []; + Module.async_finish = [ + // Always contains at least one async promise, to avoid firing immediately if nothing is added. + new Promise(function(accept, reject) { + setTimeout(accept, 0); + }) + ]; }); + /* clang-format on */ os->get_main_loop()->finish(); os->finalize_async(); // Will add all the async finish functions. EM_ASM({ @@ -79,13 +101,35 @@ extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) { ResourceLoader::set_abort_on_missing_resources(false); Main::start(); os->get_main_loop()->init(); - emscripten_resume_main_loop(); // Immediately run the first iteration. // We are inside an animation frame, we want to immediately draw on the newly setup canvas. main_loop_callback(); + emscripten_resume_main_loop(); } int main(int argc, char *argv[]) { + // Create and mount userfs immediately. + EM_ASM({ + FS.mkdir('/userfs'); + FS.mount(IDBFS, {}, '/userfs'); + }); + + // Configure locale. + char locale_ptr[16]; + /* clang-format off */ + EM_ASM({ + stringToUTF8(Module['locale'], $0, 16); + }, locale_ptr); + /* clang-format on */ + setenv("LANG", locale_ptr, true); + + // Ensure the canvas ID. + /* clang-format off */ + EM_ASM({ + stringToUTF8("#" + Module['canvas'].id, $0, 255); + }, DisplayServerJavaScript::canvas_id); + /* clang-format on */ + os = new OS_JavaScript(); Main::setup(argv[0], argc - 1, &argv[1], false); emscripten_set_main_loop(main_loop_callback, -1, false); @@ -95,8 +139,6 @@ int main(int argc, char *argv[]) { // run the 'main_after_fs_sync' function. /* clang-format off */ EM_ASM({ - FS.mkdir('/userfs'); - FS.mount(IDBFS, {}, '/userfs'); FS.syncfs(true, function(err) { requestAnimationFrame(function() { ccall('main_after_fs_sync', null, ['string'], [err ? err.message : ""]); diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index ad4b5a5afa..1ff4304bcf 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -74,18 +74,12 @@ void OS_JavaScript::initialize() { EngineDebugger::register_uri_handler("ws://", RemoteDebuggerPeerWebSocket::create); EngineDebugger::register_uri_handler("wss://", RemoteDebuggerPeerWebSocket::create); #endif - - char locale_ptr[16]; - /* clang-format off */ - EM_ASM({ - stringToUTF8(Module['locale'], $0, 16); - }, locale_ptr); - /* clang-format on */ - setenv("LANG", locale_ptr, true); } void OS_JavaScript::resume_audio() { - audio_driver_javascript.resume(); + if (audio_driver_javascript) { + audio_driver_javascript->resume(); + } } void OS_JavaScript::set_main_loop(MainLoop *p_main_loop) { @@ -133,11 +127,17 @@ void OS_JavaScript::delete_main_loop() { void OS_JavaScript::finalize_async() { finalizing = true; - audio_driver_javascript.finish_async(); + if (audio_driver_javascript) { + audio_driver_javascript->finish_async(); + } } void OS_JavaScript::finalize() { delete_main_loop(); + if (audio_driver_javascript) { + memdelete(audio_driver_javascript); + audio_driver_javascript = nullptr; + } } // Miscellaneous @@ -246,7 +246,10 @@ void OS_JavaScript::initialize_joypads() { } OS_JavaScript::OS_JavaScript() { - AudioDriverManager::add_driver(&audio_driver_javascript); + if (AudioDriverJavaScript::is_available()) { + audio_driver_javascript = memnew(AudioDriverJavaScript); + AudioDriverManager::add_driver(audio_driver_javascript); + } Vector<Logger *> loggers; loggers.push_back(memnew(StdLogger)); diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index f0f18b44f8..22234f9355 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -40,7 +40,7 @@ class OS_JavaScript : public OS_Unix { MainLoop *main_loop = nullptr; - AudioDriverJavaScript audio_driver_javascript; + AudioDriverJavaScript *audio_driver_javascript = nullptr; bool finalizing = false; bool idb_available = false; @@ -83,6 +83,9 @@ public: String get_executable_path() const; virtual Error shell_open(String p_uri); virtual String get_name() const; + // Override default OS implementation which would block the main thread with delay_usec. + // Implemented in javascript_main.cpp loop callback instead. + virtual void add_frame_delay(bool p_can_draw) {} virtual bool can_draw() const; virtual String get_cache_path() const; diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index a0954600a2..dc14580d92 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -32,12 +32,12 @@ #ifdef X11_ENABLED -#include "detect_prime_x11.h" - -#include "core/os/dir_access.h" #include "core/print_string.h" -#include "errno.h" +#include "core/project_settings.h" +#include "detect_prime_x11.h" #include "key_mapping_x11.h" +#include "main/main.h" +#include "scene/resources/texture.h" #if defined(OPENGL_ENABLED) #include "drivers/gles2/rasterizer_gles2.h" @@ -47,20 +47,14 @@ #include "servers/rendering/rasterizer_rd/rasterizer_rd.h" #endif -#include "scene/resources/texture.h" - -#ifdef HAVE_MNTENT -#include <mntent.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "X11/Xutil.h" +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#include <X11/extensions/Xinerama.h> -#include "X11/Xatom.h" -#include "X11/extensions/Xinerama.h" // ICCCM #define WM_NormalState 1L // window normal state #define WM_IconicState 3L // window minimized @@ -69,8 +63,6 @@ #define _NET_WM_STATE_ADD 1L // add/set property #define _NET_WM_STATE_TOGGLE 2L // toggle property -#include "main/main.h" - #include <dlfcn.h> #include <fcntl.h> #include <sys/stat.h> @@ -82,14 +74,9 @@ #undef KEY_TAB #endif -#include <X11/Xatom.h> - #undef CursorShape - #include <X11/XKBlib.h> -#include "core/project_settings.h" - // 2.2 is the first release with multitouch #define XINPUT_CLIENT_VERSION_MAJOR 2 #define XINPUT_CLIENT_VERSION_MINOR 2 @@ -417,17 +404,24 @@ void DisplayServerX11::mouse_warp_to_position(const Point2i &p_to) { if (mouse_mode == MOUSE_MODE_CAPTURED) { last_mouse_pos = p_to; } else { - /*XWindowAttributes xwa; - XGetWindowAttributes(x11_display, x11_window, &xwa); - printf("%d %d\n", xwa.x, xwa.y); needed? */ - XWarpPointer(x11_display, None, windows[MAIN_WINDOW_ID].x11_window, 0, 0, 0, 0, (int)p_to.x, (int)p_to.y); } } Point2i DisplayServerX11::mouse_get_position() const { - return last_mouse_pos; + int root_x, root_y; + int win_x, win_y; + unsigned int mask_return; + Window window_returned; + + Bool result = XQueryPointer(x11_display, RootWindow(x11_display, DefaultScreen(x11_display)), &window_returned, + &window_returned, &root_x, &root_y, &win_x, &win_y, + &mask_return); + if (result == True) { + return Point2i(root_x, root_y); + } + return Point2i(); } Point2i DisplayServerX11::mouse_get_absolute_position() const { @@ -735,6 +729,14 @@ ObjectID DisplayServerX11::window_get_attached_instance_id(WindowID p_window) co } DisplayServerX11::WindowID DisplayServerX11::get_window_at_screen_position(const Point2i &p_position) const { +#warning This is an incorrect implementation, if windows overlap, it should return the topmost visible one or none if occluded by a foreign window + + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + Rect2i win_rect = Rect2i(window_get_position(E->key()), window_get_size(E->key())); + if (win_rect.has_point(p_position)) { + return E->key(); + } + } return INVALID_WINDOW_ID; } @@ -1098,18 +1100,19 @@ Size2i DisplayServerX11::window_get_real_size(WindowID p_window) const { return Size2i(w, h); } -bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { - _THREAD_SAFE_METHOD_ - +// Just a helper to reduce code duplication in `window_is_maximize_allowed` +// and `_set_wm_maximized`. +bool DisplayServerX11::_window_maximize_check(WindowID p_window, const char *p_atom_name) const { ERR_FAIL_COND_V(!windows.has(p_window), false); const WindowData &wd = windows[p_window]; - Atom property = XInternAtom(x11_display, "_NET_WM_ALLOWED_ACTIONS", False); + Atom property = XInternAtom(x11_display, p_atom_name, False); Atom type; int format; unsigned long len; unsigned long remaining; unsigned char *data = nullptr; + bool retval = false; int result = XGetWindowProperty( x11_display, @@ -1141,13 +1144,20 @@ bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { } if (found_wm_act_max_horz || found_wm_act_max_vert) { - return true; + retval = true; + break; } } - XFree(atoms); + + XFree(data); } - return false; + return retval; +} + +bool DisplayServerX11::window_is_maximize_allowed(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + return _window_maximize_check(p_window, "_NET_WM_ALLOWED_ACTIONS"); } void DisplayServerX11::_set_wm_maximized(WindowID p_window, bool p_enabled) { @@ -1385,60 +1395,14 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c if (wd.fullscreen) { //if fullscreen, it's not in another mode return WINDOW_MODE_FULLSCREEN; } - { //test maximized - // Using EWMH -- Extended Window Manager Hints - Atom property = XInternAtom(x11_display, "_NET_WM_STATE", False); - Atom type; - int format; - unsigned long len; - unsigned long remaining; - unsigned char *data = nullptr; - bool retval = false; - int result = XGetWindowProperty( - x11_display, - wd.x11_window, - property, - 0, - 1024, - False, - XA_ATOM, - &type, - &format, - &len, - &remaining, - &data); - - if (result == Success && data) { - Atom *atoms = (Atom *)data; - Atom wm_max_horz = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - Atom wm_max_vert = XInternAtom(x11_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - bool found_wm_max_horz = false; - bool found_wm_max_vert = false; - - for (uint64_t i = 0; i < len; i++) { - if (atoms[i] == wm_max_horz) { - found_wm_max_horz = true; - } - if (atoms[i] == wm_max_vert) { - found_wm_max_vert = true; - } - - if (found_wm_max_horz && found_wm_max_vert) { - retval = true; - break; - } - } - - XFree(data); - } - - if (retval) { - return WINDOW_MODE_MAXIMIZED; - } + // Test maximized. + // Using EWMH -- Extended Window Manager Hints + if (_window_maximize_check(p_window, "_NET_WM_STATE")) { + return WINDOW_MODE_MAXIMIZED; } - { // test minimzed + { // Test minimized. // Using ICCCM -- Inter-Client Communication Conventions Manual Atom property = XInternAtom(x11_display, "WM_STATE", True); Atom type; @@ -1471,7 +1435,7 @@ DisplayServer::WindowMode DisplayServerX11::window_get_mode(WindowID p_window) c } } - // all other discarded, return windowed. + // All other discarded, return windowed. return WINDOW_MODE_WINDOWED; } @@ -2394,6 +2358,30 @@ void DisplayServerX11::_send_window_event(const WindowData &wd, WindowEvent p_ev void DisplayServerX11::process_events() { _THREAD_SAFE_METHOD_ + if (app_focused) { + //verify that one of the windows has focus, else send focus out notification + bool focus_found = false; + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { + if (E->get().focused) { + focus_found = true; + } + } + + if (!focus_found) { + uint64_t delta = OS::get_singleton()->get_ticks_msec() - time_since_no_focus; + + if (delta > 250) { + //X11 can go between windows and have no focus for a while, when creating them or something else. Use this as safety to avoid unnecesary focus in/outs. + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } + app_focused = false; + } + } else { + time_since_no_focus = OS::get_singleton()->get_ticks_msec(); + } + } + do_mouse_warp = false; // Is the current mouse mode one where it needs to be grabbed. @@ -2588,12 +2576,12 @@ void DisplayServerX11::process_events() { break; case NoExpose: - minimized = true; + windows[window_id].minimized = true; break; case VisibilityNotify: { XVisibilityEvent *visibility = (XVisibilityEvent *)&event; - minimized = (visibility->state == VisibilityFullyObscured); + windows[window_id].minimized = (visibility->state == VisibilityFullyObscured); } break; case LeaveNotify: { if (!mouse_mode_grab) { @@ -2607,10 +2595,8 @@ void DisplayServerX11::process_events() { } } break; case FocusIn: - minimized = false; - window_has_focus = true; + windows[window_id].focused = true; _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_IN); - window_focused = true; if (mouse_mode_grab) { // Show and update the cursor if confined and the window regained focus. @@ -2637,13 +2623,19 @@ void DisplayServerX11::process_events() { if (windows[window_id].xic) { XSetICFocus(windows[window_id].xic); } + + if (!app_focused) { + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } + app_focused = true; + } break; case FocusOut: - window_has_focus = false; + windows[window_id].focused = false; Input::get_singleton()->release_pressed_events(); _send_window_event(windows[window_id], WINDOW_EVENT_FOCUS_OUT); - window_focused = false; if (mouse_mode_grab) { for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { @@ -2782,7 +2774,7 @@ void DisplayServerX11::process_events() { Point2i new_center = pos; pos = last_mouse_pos + xi.relative_motion; center = new_center; - do_mouse_warp = window_has_focus; // warp the cursor if we're focused in + do_mouse_warp = windows[window_id].focused; // warp the cursor if we're focused in } if (!last_mouse_pos_valid) { @@ -2842,7 +2834,7 @@ void DisplayServerX11::process_events() { // Don't propagate the motion event unless we have focus // this is so that the relative motion doesn't get messed up // after we regain focus. - if (window_has_focus || !mouse_mode_grab) { + if (windows[window_id].focused || !mouse_mode_grab) { Input::get_singleton()->accumulate_input_event(mm); } @@ -3819,8 +3811,6 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode requested = None; - window_has_focus = true; // Set focus to true at init - /*if (p_desired.layered) { set_window_per_pixel_transparency_enabled(true); }*/ diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index f01b9a2323..b5d2ea1c63 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -36,7 +36,6 @@ #include "servers/display_server.h" #include "core/input/input.h" - #include "drivers/alsa/audio_driver_alsa.h" #include "drivers/alsamidi/midi_driver_alsamidi.h" #include "drivers/pulseaudio/audio_driver_pulseaudio.h" @@ -140,6 +139,8 @@ class DisplayServerX11 : public DisplayServer { bool borderless = false; bool resize_disabled = false; Vector2i last_position_before_fs; + bool focused = false; + bool minimized = false; }; Map<WindowID, WindowData> windows; @@ -165,6 +166,8 @@ class DisplayServerX11 : public DisplayServer { uint64_t last_click_ms; int last_click_button_index; uint32_t last_button_state; + bool app_focused = false; + uint64_t time_since_no_focus = 0; struct { int opcode; @@ -196,8 +199,8 @@ class DisplayServerX11 : public DisplayServer { void _handle_key_event(WindowID p_window, XKeyEvent *p_event, bool p_echo = false); - bool minimized; - bool window_has_focus; + //bool minimized; + //bool window_has_focus; bool do_mouse_warp; const char *cursor_theme; @@ -211,7 +214,7 @@ class DisplayServerX11 : public DisplayServer { bool layered_window; String rendering_driver; - bool window_focused; + //bool window_focused; //void set_wm_border(bool p_enabled); void set_wm_fullscreen(bool p_enabled); void set_wm_above(bool p_enabled); @@ -231,6 +234,7 @@ class DisplayServerX11 : public DisplayServer { static Property _read_property(Display *p_display, Window p_window, Atom p_property); void _update_real_mouse_position(const WindowData &wd); + bool _window_maximize_check(WindowID p_window, const char *p_atom_name) const; void _set_wm_fullscreen(WindowID p_window, bool p_enabled); void _set_wm_maximized(WindowID p_window, bool p_enabled); diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 09a5eca914..8c6f3b1167 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -31,8 +31,11 @@ #include "os_linuxbsd.h" #include "core/os/dir_access.h" -#include "core/print_string.h" -#include "errno.h" +#include "main/main.h" + +#ifdef X11_ENABLED +#include "display_server_x11.h" +#endif #ifdef HAVE_MNTENT #include <mntent.h> @@ -48,12 +51,6 @@ #include <sys/types.h> #include <unistd.h> -#include "main/main.h" - -#ifdef X11_ENABLED -#include "display_server_x11.h" -#endif - void OS_LinuxBSD::initialize() { crash_handler.initialize(); diff --git a/platform/osx/detect.py b/platform/osx/detect.py index 29aa8ece19..ff4c024551 100644 --- a/platform/osx/detect.py +++ b/platform/osx/detect.py @@ -87,8 +87,15 @@ def configure(env): env["osxcross"] = True if not "osxcross" in env: # regular native build - env.Append(CCFLAGS=["-arch", "x86_64"]) - env.Append(LINKFLAGS=["-arch", "x86_64"]) + if env["arch"] == "arm64": + print("Building for macOS 10.15+, platform arm64.") + env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15", "-target", "arm64-apple-macos10.15"]) + env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15", "-target", "arm64-apple-macos10.15"]) + else: + print("Building for macOS 10.12+, platform x86-64.") + env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"]) + env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"]) + if env["macports_clang"] != "no": mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local") mpclangver = env["macports_clang"] @@ -148,7 +155,8 @@ def configure(env): ## Dependencies if env["builtin_libtheora"]: - env["x86_libtheora_opt_gcc"] = True + if env["arch"] != "arm64": + env["x86_libtheora_opt_gcc"] = True ## Flags @@ -189,6 +197,3 @@ def configure(env): env.Append(LIBS=["vulkan"]) # env.Append(CPPDEFINES=['GLES_ENABLED', 'OPENGL_ENABLED']) - - env.Append(CCFLAGS=["-mmacosx-version-min=10.12"]) - env.Append(LINKFLAGS=["-mmacosx-version-min=10.12"]) diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index fddb1d0ca6..8e27f10dc2 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -86,6 +86,14 @@ public: uint32_t unicode; }; + struct WarpEvent { + NSTimeInterval timestamp; + NSPoint delta; + }; + + List<WarpEvent> warp_events; + NSTimeInterval last_warp = 0; + Vector<KeyEvent> key_event_buffer; int key_event_pos; @@ -220,7 +228,7 @@ public: virtual Vector<int> get_window_list() const; - virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i & = Rect2i()); + virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); virtual void delete_sub_window(WindowID p_id); virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID); diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 920fd24c4a..e3b29fc047 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -197,6 +197,18 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { } } +- (void)applicationDidResignActive:(NSNotification *)notification { + if (OS_OSX::get_singleton()->get_main_loop()) { + OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + if (OS_OSX::get_singleton()->get_main_loop()) { + OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } +} + - (void)globalMenuCallback:(id)sender { if (![sender representedObject]) return; @@ -566,7 +578,11 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { trackingArea = nil; imeInputEventInProgress = false; [self updateTrackingAreas]; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 + [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeFileURL]]; +#else [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; +#endif markedText = [[NSMutableAttributedString alloc] init]; return self; } @@ -723,11 +739,19 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; NSPasteboard *pboard = [sender draggingPasteboard]; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 + NSArray<NSURL *> *filenames = [pboard propertyListForType:NSPasteboardTypeFileURL]; +#else NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType]; +#endif Vector<String> files; for (NSUInteger i = 0; i < filenames.count; i++) { +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 + NSString *ns = [[filenames objectAtIndex:i] path]; +#else NSString *ns = [filenames objectAtIndex:i]; +#endif char *utfs = strdup([ns UTF8String]); String ret; ret.parse_utf8(utfs); @@ -824,13 +848,59 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i ERR_FAIL_COND(!DS_OSX->windows.has(window_id)); DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; + NSPoint delta = NSMakePoint([event deltaX], [event deltaY]); + NSPoint mpos = [event locationInWindow]; + + if (DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CONFINED) { + // Discard late events + if (([event timestamp]) < DS_OSX->last_warp) { + return; + } + + // Warp affects next event delta, subtract previous warp deltas + List<DisplayServerOSX::WarpEvent>::Element *F = DS_OSX->warp_events.front(); + while (F) { + if (F->get().timestamp < [event timestamp]) { + List<DisplayServerOSX::WarpEvent>::Element *E = F; + delta.x -= E->get().delta.x; + delta.y -= E->get().delta.y; + F = F->next(); + DS_OSX->warp_events.erase(E); + } else { + F = F->next(); + } + } + + // Confine mouse position to the window, and update delta + NSRect frame = [wd.window_object frame]; + NSPoint conf_pos = mpos; + conf_pos.x = CLAMP(conf_pos.x + delta.x, 0.f, frame.size.width); + conf_pos.y = CLAMP(conf_pos.y - delta.y, 0.f, frame.size.height); + delta.x = conf_pos.x - mpos.x; + delta.y = mpos.y - conf_pos.y; + mpos = conf_pos; + + // Move mouse cursor + NSRect pointInWindowRect = NSMakeRect(conf_pos.x, conf_pos.y, 0, 0); + conf_pos = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin; + conf_pos.y = CGDisplayBounds(CGMainDisplayID()).size.height - conf_pos.y; + CGWarpMouseCursorPosition(conf_pos); + + // Save warp data + DS_OSX->last_warp = [[NSProcessInfo processInfo] systemUptime]; + DisplayServerOSX::WarpEvent ev; + ev.timestamp = DS_OSX->last_warp; + ev.delta = delta; + DS_OSX->warp_events.push_back(ev); + } + Ref<InputEventMouseMotion> mm; mm.instance(); mm->set_window_id(window_id); mm->set_button_mask(DS_OSX->last_button_state); const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0; - const Vector2i pos = _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor); + const Vector2i pos = _get_mouse_pos(wd, mpos, backingScaleFactor); mm->set_position(pos); mm->set_pressure([event pressure]); if ([event subtype] == NSEventSubtypeTabletPoint) { @@ -839,9 +909,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i } mm->set_global_position(pos); mm->set_speed(Input::get_singleton()->get_last_mouse_speed()); - Vector2i relativeMotion = Vector2i(); - relativeMotion.x = [event deltaX] * backingScaleFactor; - relativeMotion.y = [event deltaY] * backingScaleFactor; + const Vector2i relativeMotion = Vector2i(delta.x, delta.y) * backingScaleFactor; mm->set_relative(relativeMotion); _get_key_modifier_state([event modifierFlags], mm); @@ -1946,11 +2014,15 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { CGDisplayHideCursor(kCGDirectMainDisplay); } CGAssociateMouseAndMouseCursorPosition(true); + } else if (p_mode == MOUSE_MODE_CONFINED) { + CGDisplayShowCursor(kCGDirectMainDisplay); + CGAssociateMouseAndMouseCursorPosition(false); } else { CGDisplayShowCursor(kCGDirectMainDisplay); CGAssociateMouseAndMouseCursorPosition(true); } + warp_events.clear(); mouse_mode = p_mode; } @@ -1980,7 +2052,9 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) { CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0); CGAssociateMouseAndMouseCursorPosition(false); CGWarpMouseCursorPosition(lMouseWarpPos); - CGAssociateMouseAndMouseCursorPosition(true); + if (mouse_mode != MOUSE_MODE_CONFINED) { + CGAssociateMouseAndMouseCursorPosition(true); + } } } @@ -3300,6 +3374,8 @@ String DisplayServerOSX::ime_get_text() const { } DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Point2i &p_position) const { +#warning This is an incorrect implementation, if windows overlap, it should return the topmost visible one or none if occluded by a foreign window + for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { Rect2i win_rect = Rect2i(window_get_position(E->key()), window_get_size(E->key())); if (win_rect.has_point(p_position)) { diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 9af7c02351..916816325d 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -825,14 +825,15 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String zipfi.tmz_date.tm_hour = time.hour; zipfi.tmz_date.tm_mday = date.day; zipfi.tmz_date.tm_min = time.min; - zipfi.tmz_date.tm_mon = date.month; + zipfi.tmz_date.tm_mon = date.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, http://www.cplusplus.com/reference/ctime/tm/ zipfi.tmz_date.tm_sec = time.sec; zipfi.tmz_date.tm_year = date.year; zipfi.dosDate = 0; // 0100000: regular file type // 0000755: permissions rwxr-xr-x // 0000644: permissions rw-r--r-- - zipfi.external_fa = (is_executable ? 0100755 : 0100644) << 16L; + uint32_t _mode = (is_executable ? 0100755 : 0100644); + zipfi.external_fa = (_mode << 16L) | !(_mode & 0200); zipfi.internal_fa = 0; zipOpenNewFileInZip4(p_zip, diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index f47afcc4e5..103e858d97 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -476,6 +476,7 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod _THREAD_SAFE_METHOD_ WindowID window_id = _create_window(p_mode, p_flags, p_rect); + ERR_FAIL_COND_V_MSG(window_id == INVALID_WINDOW_ID, INVALID_WINDOW_ID, "Failed to create sub window."); WindowData &wd = windows[window_id]; @@ -1773,14 +1774,22 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA }; WindowID window_id = INVALID_WINDOW_ID; + bool window_created = false; for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { if (E->get().hWnd == hWnd) { window_id = E->key(); + window_created = true; break; } } + if (!window_created) { + // Window creation in progress. + window_id = window_id_counter; + ERR_FAIL_COND_V(!windows.has(window_id), 0); + } + switch (uMsg) // Check For Windows Messages { case WM_SETFOCUS: { @@ -1790,6 +1799,12 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA // Restore mouse mode _set_mouse_mode_impl(mouse_mode); + if (!app_focused) { + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } + app_focused = true; + } break; } case WM_KILLFOCUS: { @@ -1805,6 +1820,19 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } touch_state.clear(); + bool self_steal = false; + HWND new_hwnd = (HWND)wParam; + if (IsWindow(new_hwnd)) { + self_steal = true; + } + + if (!self_steal) { + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } + app_focused = false; + } + break; } case WM_ACTIVATE: // Watch For Window Activate Message @@ -2493,7 +2521,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA windows[window_id].height = window_h; #if defined(VULKAN_ENABLED) - if (rendering_driver == "vulkan") { + if ((rendering_driver == "vulkan") && window_created) { context_vulkan->window_resize(window_id, windows[window_id].width, windows[window_id].height); } #endif @@ -2845,11 +2873,32 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, WindowRect.top = p_rect.position.y; WindowRect.bottom = p_rect.position.y + p_rect.size.y; + if (p_mode == WINDOW_MODE_FULLSCREEN) { + int nearest_area = 0; + Rect2i screen_rect; + for (int i = 0; i < get_screen_count(); i++) { + Rect2i r; + r.position = screen_get_position(i); + r.size = screen_get_size(i); + Rect2 inters = r.clip(p_rect); + int area = inters.size.width * inters.size.height; + if (area >= nearest_area) { + screen_rect = r; + nearest_area = area; + } + } + + WindowRect.left = screen_rect.position.x; + WindowRect.right = screen_rect.position.x + screen_rect.size.x; + WindowRect.top = screen_rect.position.y; + WindowRect.bottom = screen_rect.position.y + screen_rect.size.y; + } + AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); WindowID id = window_id_counter; { - WindowData wd; + WindowData &wd = windows[id]; wd.hWnd = CreateWindowExW( dwExStyle, @@ -2864,6 +2913,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, nullptr, nullptr, hInstance, nullptr); if (!wd.hWnd) { MessageBoxW(nullptr, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); + windows.erase(id); return INVALID_WINDOW_ID; } #ifdef VULKAN_ENABLED @@ -2872,7 +2922,8 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, if (context_vulkan->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) { memdelete(context_vulkan); context_vulkan = nullptr; - ERR_FAIL_V(INVALID_WINDOW_ID); + windows.erase(id); + ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Failed to create Vulkan Window."); } } #endif @@ -2930,8 +2981,6 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, wd.width = p_rect.size.width; wd.height = p_rect.size.height; - windows[id] = wd; - window_id_counter++; } @@ -3062,7 +3111,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win Point2i window_position( (screen_get_size(0).width - p_resolution.width) / 2, (screen_get_size(0).height - p_resolution.height) / 2); + WindowID main_window = _create_window(p_mode, 0, Rect2i(window_position, p_resolution)); + ERR_FAIL_COND_MSG(main_window == INVALID_WINDOW_ID, "Failed to create main window."); + for (int i = 0; i < WINDOW_FLAG_MAX; i++) { if (p_flags & (1 << i)) { window_set_flag(WindowFlags(i), true, main_window); diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 995ced0809..8433bb449b 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -317,6 +317,7 @@ private: int pressrc; HINSTANCE hInstance; // Holds The Instance Of The Application String rendering_driver; + bool app_focused = false; struct WindowData { HWND hWnd; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 88d124536c..d022c857f3 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -176,11 +176,14 @@ String CollisionShape2D::get_configuration_warning() const { if (!Object::cast_to<CollisionObject2D>(get_parent())) { return TTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, KinematicBody2D, etc. to give them a shape."); } - if (!shape.is_valid()) { return TTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!"); } - + Ref<ConvexPolygonShape2D> convex = shape; + Ref<ConcavePolygonShape2D> concave = shape; + if (convex.is_valid() || concave.is_valid()) { + return TTR("Polygon-based shapes are not meant be used nor edited directly through the CollisionShape2D node. Please use the CollisionPolygon2D node instead."); + } return String(); } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 84560b843b..0a9de20664 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -631,8 +631,8 @@ void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) { PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } -void RigidBody2D::apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse) { - PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_offset, p_impulse); +void RigidBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) { + PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position); } void RigidBody2D::apply_torque_impulse(float p_torque) { @@ -659,8 +659,8 @@ void RigidBody2D::add_central_force(const Vector2 &p_force) { PhysicsServer2D::get_singleton()->body_add_central_force(get_rid(), p_force); } -void RigidBody2D::add_force(const Vector2 &p_offset, const Vector2 &p_force) { - PhysicsServer2D::get_singleton()->body_add_force(get_rid(), p_offset, p_force); +void RigidBody2D::add_force(const Vector2 &p_force, const Vector2 &p_position) { + PhysicsServer2D::get_singleton()->body_add_force(get_rid(), p_force, p_position); } void RigidBody2D::add_torque(const float p_torque) { @@ -801,8 +801,8 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode); ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "offset", "impulse"), &RigidBody2D::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse, Vector2()); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody2D::apply_impulse, Vector2()); ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse); ClassDB::bind_method(D_METHOD("set_applied_force", "force"), &RigidBody2D::set_applied_force); @@ -812,7 +812,7 @@ void RigidBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_applied_torque"), &RigidBody2D::get_applied_torque); ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidBody2D::add_central_force); - ClassDB::bind_method(D_METHOD("add_force", "offset", "force"), &RigidBody2D::add_force); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody2D::add_force, Vector2()); ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidBody2D::add_torque); ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index cde4398ad3..936cc9b7ac 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -237,7 +237,7 @@ public: CCDMode get_continuous_collision_detection_mode() const; void apply_central_impulse(const Vector2 &p_impulse); - void apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse); + void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()); void apply_torque_impulse(float p_torque); void set_applied_force(const Vector2 &p_force); @@ -247,7 +247,7 @@ public: float get_applied_torque() const; void add_central_force(const Vector2 &p_force); - void add_force(const Vector2 &p_offset, const Vector2 &p_force); + void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()); void add_torque(float p_torque); TypedArray<Node2D> get_colliding_bodies() const; //function for script diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index 5020940c5c..9fd24b5294 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -325,8 +325,7 @@ void RayCast2D::_bind_methods() { } RayCast2D::RayCast2D() { - enabled = false; - + enabled = true; collided = false; against_shape = 0; collision_mask = 1; diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index a41eaf9da0..e867891ec0 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -894,13 +894,13 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_image_d if (Object::cast_to<DirectionalLight3D>(light)) { DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light); - lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); + lightmapper->add_directional_light(light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_SIZE)); } else if (Object::cast_to<OmniLight3D>(light)) { OmniLight3D *l = Object::cast_to<OmniLight3D>(light); - lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + lightmapper->add_omni_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); } else if (Object::cast_to<SpotLight3D>(light)) { SpotLight3D *l = Object::cast_to<SpotLight3D>(light); - lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); + lightmapper->add_spot_light(light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light3D::PARAM_ENERGY), l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE)); } } for (int i = 0; i < probes_found.size(); i++) { diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 7ffca4bd9e..ecbaca7bd1 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -35,6 +35,7 @@ #include "core/math/camera_matrix.h" #include "scene/resources/material.h" #include "scene/resources/surface_tool.h" + void Camera3D::_update_audio_listener_state() { } @@ -318,8 +319,8 @@ Vector3 Camera3D::project_ray_origin(const Point2 &p_pos) const { bool Camera3D::is_position_behind(const Vector3 &p_pos) const { Transform t = get_global_transform(); - Vector3 eyedir = -get_global_transform().basis.get_axis(2).normalized(); - return eyedir.dot(p_pos) < (eyedir.dot(t.origin) + near); + Vector3 eyedir = -t.basis.get_axis(2).normalized(); + return eyedir.dot(p_pos - t.origin) < near; } Vector<Vector3> Camera3D::get_near_plane_points() const { diff --git a/scene/3d/camera_3d.h b/scene/3d/camera_3d.h index 138b1b8a7a..5c9431e08a 100644 --- a/scene/3d/camera_3d.h +++ b/scene/3d/camera_3d.h @@ -34,6 +34,7 @@ #include "scene/3d/node_3d.h" #include "scene/3d/velocity_tracker_3d.h" #include "scene/main/window.h" +#include "scene/resources/camera_effects.h" #include "scene/resources/environment.h" class Camera3D : public Node3D { diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 9270b548b7..cc1622722e 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -144,7 +144,7 @@ Vector<Face3> Light3D::get_faces(uint32_t p_usage_flags) const { void Light3D::set_bake_mode(BakeMode p_mode) { bake_mode = p_mode; - RS::get_singleton()->light_set_use_gi(light, p_mode != BAKE_DISABLED); + RS::get_singleton()->light_set_bake_mode(light, RS::LightBakeMode(p_mode)); } Light3D::BakeMode Light3D::get_bake_mode() const { @@ -261,7 +261,7 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01"), "set_param", "get_param", PARAM_SIZE); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR); - ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disable,Indirect,All"), "set_bake_mode", "get_bake_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static"), "set_bake_mode", "get_bake_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow"); @@ -296,8 +296,8 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_MAX); BIND_ENUM_CONSTANT(BAKE_DISABLED); - BIND_ENUM_CONSTANT(BAKE_INDIRECT); - BIND_ENUM_CONSTANT(BAKE_ALL); + BIND_ENUM_CONSTANT(BAKE_DYNAMIC); + BIND_ENUM_CONSTANT(BAKE_STATIC); } Light3D::Light3D(RenderingServer::LightType p_type) { @@ -319,7 +319,7 @@ Light3D::Light3D(RenderingServer::LightType p_type) { RS::get_singleton()->instance_set_base(get_instance(), light); reverse_cull = false; - bake_mode = BAKE_INDIRECT; + bake_mode = BAKE_DYNAMIC; editor_only = false; set_color(Color(1, 1, 1, 1)); diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index f16773f6ae..71df1b5ded 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef LIGHT_H -#define LIGHT_H +#ifndef LIGHT_3D_H +#define LIGHT_3D_H #include "scene/3d/visual_instance_3d.h" #include "scene/resources/texture.h" @@ -64,8 +64,8 @@ public: enum BakeMode { BAKE_DISABLED, - BAKE_INDIRECT, - BAKE_ALL + BAKE_DYNAMIC, + BAKE_STATIC }; private: @@ -145,7 +145,7 @@ public: enum ShadowMode { SHADOW_ORTHOGONAL, SHADOW_PARALLEL_2_SPLITS, - SHADOW_PARALLEL_4_SPLITS + SHADOW_PARALLEL_4_SPLITS, }; enum ShadowDepthRange { @@ -217,4 +217,4 @@ public: Light3D(RenderingServer::LIGHT_SPOT) {} }; -#endif +#endif // LIGHT_3D_H diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index 6320af21eb..fda072e233 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -638,8 +638,9 @@ void RigidBody3D::add_central_force(const Vector3 &p_force) { PhysicsServer3D::get_singleton()->body_add_central_force(get_rid(), p_force); } -void RigidBody3D::add_force(const Vector3 &p_force, const Vector3 &p_pos) { - PhysicsServer3D::get_singleton()->body_add_force(get_rid(), p_force, p_pos); +void RigidBody3D::add_force(const Vector3 &p_force, const Vector3 &p_position) { + PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); + singleton->body_add_force(get_rid(), p_force, p_position); } void RigidBody3D::add_torque(const Vector3 &p_torque) { @@ -650,8 +651,9 @@ void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) { PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } -void RigidBody3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); +void RigidBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { + PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); + singleton->body_apply_impulse(get_rid(), p_impulse, p_position); } void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) { @@ -782,11 +784,11 @@ void RigidBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody3D::set_axis_velocity); ClassDB::bind_method(D_METHOD("add_central_force", "force"), &RigidBody3D::add_central_force); - ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody3D::add_force); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &RigidBody3D::add_force, Vector3()); ClassDB::bind_method(D_METHOD("add_torque", "torque"), &RigidBody3D::add_torque); ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody3D::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &RigidBody3D::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody3D::apply_impulse, Vector3()); ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody3D::apply_torque_impulse); ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody3D::set_sleeping); @@ -1372,8 +1374,8 @@ void PhysicalBone3D::apply_central_impulse(const Vector3 &p_impulse) { PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } -void PhysicalBone3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); +void PhysicalBone3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { + PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position); } void PhysicalBone3D::reset_physics_simulation_state() { @@ -2099,7 +2101,7 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) { void PhysicalBone3D::_bind_methods() { ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicalBone3D::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "position", "impulse"), &PhysicalBone3D::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicalBone3D::apply_impulse, Vector3()); ClassDB::bind_method(D_METHOD("_direct_state_changed"), &PhysicalBone3D::_direct_state_changed); diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 4c58c73942..e846b7a7f8 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -234,11 +234,11 @@ public: Array get_colliding_bodies() const; void add_central_force(const Vector3 &p_force); - void add_force(const Vector3 &p_force, const Vector3 &p_pos); + void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()); void add_torque(const Vector3 &p_torque); void apply_central_impulse(const Vector3 &p_impulse); - void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); void apply_torque_impulse(const Vector3 &p_impulse); virtual String get_configuration_warning() const; @@ -597,7 +597,7 @@ public: bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const; void apply_central_impulse(const Vector3 &p_impulse); - void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); void reset_physics_simulation_state(); void reset_to_rest_position(); diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index 68f4b3132c..2a922e3cda 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -383,8 +383,7 @@ void RayCast3D::_clear_debug_shape() { } RayCast3D::RayCast3D() { - enabled = false; - + enabled = true; collided = false; against_shape = 0; collision_mask = 1; diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index b1f19053d9..c7948395d3 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -39,31 +39,32 @@ float ReflectionProbe::get_intensity() const { return intensity; } -void ReflectionProbe::set_interior_ambient(Color p_ambient) { - interior_ambient = p_ambient; - RS::get_singleton()->reflection_probe_set_interior_ambient(probe, p_ambient); +void ReflectionProbe::set_ambient_mode(AmbientMode p_mode) { + ambient_mode = p_mode; + RS::get_singleton()->reflection_probe_set_ambient_mode(probe, RS::ReflectionProbeAmbientMode(p_mode)); + _change_notify(); } -void ReflectionProbe::set_interior_ambient_energy(float p_energy) { - interior_ambient_energy = p_energy; - RS::get_singleton()->reflection_probe_set_interior_ambient_energy(probe, p_energy); +ReflectionProbe::AmbientMode ReflectionProbe::get_ambient_mode() const { + return ambient_mode; } -float ReflectionProbe::get_interior_ambient_energy() const { - return interior_ambient_energy; +void ReflectionProbe::set_ambient_color(Color p_ambient) { + ambient_color = p_ambient; + RS::get_singleton()->reflection_probe_set_ambient_color(probe, p_ambient); } -Color ReflectionProbe::get_interior_ambient() const { - return interior_ambient; +void ReflectionProbe::set_ambient_color_energy(float p_energy) { + ambient_color_energy = p_energy; + RS::get_singleton()->reflection_probe_set_ambient_energy(probe, p_energy); } -void ReflectionProbe::set_interior_ambient_probe_contribution(float p_contribution) { - interior_ambient_probe_contribution = p_contribution; - RS::get_singleton()->reflection_probe_set_interior_ambient_probe_contribution(probe, p_contribution); +float ReflectionProbe::get_ambient_color_energy() const { + return ambient_color_energy; } -float ReflectionProbe::get_interior_ambient_probe_contribution() const { - return interior_ambient_probe_contribution; +Color ReflectionProbe::get_ambient_color() const { + return ambient_color; } void ReflectionProbe::set_max_distance(float p_distance) { @@ -130,7 +131,6 @@ bool ReflectionProbe::is_box_projection_enabled() const { void ReflectionProbe::set_as_interior(bool p_enable) { interior = p_enable; RS::get_singleton()->reflection_probe_set_as_interior(probe, interior); - _change_notify(); } bool ReflectionProbe::is_set_as_interior() const { @@ -176,8 +176,8 @@ Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const { } void ReflectionProbe::_validate_property(PropertyInfo &property) const { - if (property.name == "interior/ambient_color" || property.name == "interior/ambient_energy" || property.name == "interior/ambient_contrib") { - if (!interior) { + if (property.name == "interior/ambient_color" || property.name == "interior/ambient_color_energy") { + if (ambient_mode != AMBIENT_COLOR) { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -187,14 +187,14 @@ void ReflectionProbe::_bind_methods() { ClassDB::bind_method(D_METHOD("set_intensity", "intensity"), &ReflectionProbe::set_intensity); ClassDB::bind_method(D_METHOD("get_intensity"), &ReflectionProbe::get_intensity); - ClassDB::bind_method(D_METHOD("set_interior_ambient", "ambient"), &ReflectionProbe::set_interior_ambient); - ClassDB::bind_method(D_METHOD("get_interior_ambient"), &ReflectionProbe::get_interior_ambient); + ClassDB::bind_method(D_METHOD("set_ambient_mode", "ambient"), &ReflectionProbe::set_ambient_mode); + ClassDB::bind_method(D_METHOD("get_ambient_mode"), &ReflectionProbe::get_ambient_mode); - ClassDB::bind_method(D_METHOD("set_interior_ambient_energy", "ambient_energy"), &ReflectionProbe::set_interior_ambient_energy); - ClassDB::bind_method(D_METHOD("get_interior_ambient_energy"), &ReflectionProbe::get_interior_ambient_energy); + ClassDB::bind_method(D_METHOD("set_ambient_color", "ambient"), &ReflectionProbe::set_ambient_color); + ClassDB::bind_method(D_METHOD("get_ambient_color"), &ReflectionProbe::get_ambient_color); - ClassDB::bind_method(D_METHOD("set_interior_ambient_probe_contribution", "ambient_probe_contribution"), &ReflectionProbe::set_interior_ambient_probe_contribution); - ClassDB::bind_method(D_METHOD("get_interior_ambient_probe_contribution"), &ReflectionProbe::get_interior_ambient_probe_contribution); + ClassDB::bind_method(D_METHOD("set_ambient_color_energy", "ambient_energy"), &ReflectionProbe::set_ambient_color_energy); + ClassDB::bind_method(D_METHOD("get_ambient_color_energy"), &ReflectionProbe::get_ambient_color_energy); ClassDB::bind_method(D_METHOD("set_max_distance", "max_distance"), &ReflectionProbe::set_max_distance); ClassDB::bind_method(D_METHOD("get_max_distance"), &ReflectionProbe::get_max_distance); @@ -226,24 +226,28 @@ void ReflectionProbe::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "origin_offset"), "set_origin_offset", "get_origin_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "box_projection"), "set_enable_box_projection", "is_box_projection_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_as_interior", "is_set_as_interior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_shadows"), "set_enable_shadows", "are_shadows_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask"); - ADD_GROUP("Interior", "interior_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior_enable"), "set_as_interior", "is_set_as_interior"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "interior_ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_interior_ambient", "get_interior_ambient"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_interior_ambient_energy", "get_interior_ambient_energy"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "interior_ambient_contrib", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_interior_ambient_probe_contribution", "get_interior_ambient_probe_contribution"); + ADD_GROUP("Ambient", "ambient_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_mode", PROPERTY_HINT_ENUM, "Disabled,Environment,ConstantColor"), "set_ambient_mode", "get_ambient_mode"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ambient_color", "get_ambient_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_color_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_color_energy", "get_ambient_color_energy"); BIND_ENUM_CONSTANT(UPDATE_ONCE); BIND_ENUM_CONSTANT(UPDATE_ALWAYS); + + BIND_ENUM_CONSTANT(AMBIENT_DISABLED); + BIND_ENUM_CONSTANT(AMBIENT_ENVIRONMENT); + BIND_ENUM_CONSTANT(AMBIENT_COLOR); } ReflectionProbe::ReflectionProbe() { intensity = 1.0; - interior_ambient = Color(0, 0, 0); - interior_ambient_probe_contribution = 0; - interior_ambient_energy = 1.0; + ambient_mode = AMBIENT_ENVIRONMENT; + ambient_color = Color(0, 0, 0); + ambient_color_energy = 1.0; max_distance = 0; extents = Vector3(1, 1, 1); origin_offset = Vector3(0, 0, 0); diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 3867d13435..c708804f96 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -45,6 +45,12 @@ public: UPDATE_ALWAYS, }; + enum AmbientMode { + AMBIENT_DISABLED, + AMBIENT_ENVIRONMENT, + AMBIENT_COLOR + }; + private: RID probe; float intensity; @@ -54,9 +60,9 @@ private: bool box_projection; bool enable_shadows; bool interior; - Color interior_ambient; - float interior_ambient_energy; - float interior_ambient_probe_contribution; + AmbientMode ambient_mode; + Color ambient_color; + float ambient_color_energy; uint32_t cull_mask; UpdateMode update_mode; @@ -69,11 +75,14 @@ public: void set_intensity(float p_intensity); float get_intensity() const; - void set_interior_ambient(Color p_ambient); - Color get_interior_ambient() const; + void set_ambient_mode(AmbientMode p_mode); + AmbientMode get_ambient_mode() const; + + void set_ambient_color(Color p_ambient); + Color get_ambient_color() const; - void set_interior_ambient_energy(float p_energy); - float get_interior_ambient_energy() const; + void set_ambient_color_energy(float p_energy); + float get_ambient_color_energy() const; void set_interior_ambient_probe_contribution(float p_contribution); float get_interior_ambient_probe_contribution() const; @@ -109,6 +118,7 @@ public: ~ReflectionProbe(); }; +VARIANT_ENUM_CAST(ReflectionProbe::AmbientMode); VARIANT_ENUM_CAST(ReflectionProbe::UpdateMode); #endif // REFLECTIONPROBE_H diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 9c6b940b00..4c71ab470b 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -794,7 +794,7 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) { s->get_transform().origin; if (m_forwardImpulse[wheel] != real_t(0.)) { - s->apply_impulse(rel_pos, m_forwardWS[wheel] * (m_forwardImpulse[wheel])); + s->apply_impulse(m_forwardWS[wheel] * (m_forwardImpulse[wheel]), rel_pos); } if (m_sideImpulse[wheel] != real_t(0.)) { PhysicsBody3D *groundObject = wheelInfo.m_raycastInfo.m_groundObject; @@ -812,7 +812,7 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) { #else rel_pos[1] *= wheelInfo.m_rollInfluence; //? #endif - s->apply_impulse(rel_pos, sideImp); + s->apply_impulse(sideImp, rel_pos); //apply friction impulse on the ground //todo @@ -850,10 +850,9 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) { suspensionForce = wheel.m_maxSuspensionForce; } Vector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; - Vector3 relpos = wheel.m_raycastInfo.m_contactPointWS - state->get_transform().origin; + Vector3 relative_position = wheel.m_raycastInfo.m_contactPointWS - state->get_transform().origin; - state->apply_impulse(relpos, impulse); - //getRigidBody()->applyImpulse(impulse, relpos); + state->apply_impulse(impulse, relative_position); } _update_friction(state); diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp index 24071f31f3..5e73e460ed 100644 --- a/scene/3d/world_environment.cpp +++ b/scene/3d/world_environment.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "world_environment.h" + #include "scene/main/window.h" void WorldEnvironment::_notification(int p_what) { diff --git a/scene/3d/world_environment.h b/scene/3d/world_environment.h index ddb2af7bd3..4a0dbd35a3 100644 --- a/scene/3d/world_environment.h +++ b/scene/3d/world_environment.h @@ -32,6 +32,8 @@ #define SCENARIO_FX_H #include "scene/3d/node_3d.h" +#include "scene/resources/camera_effects.h" +#include "scene/resources/environment.h" class WorldEnvironment : public Node { GDCLASS(WorldEnvironment, Node); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 319d0171b3..66c587e2d4 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1055,6 +1055,8 @@ void AnimationPlayer::get_animation_list(List<StringName> *p_animations) const { } void AnimationPlayer::set_blend_time(const StringName &p_animation1, const StringName &p_animation2, float p_time) { + ERR_FAIL_COND(!animation_set.has(p_animation1)); + ERR_FAIL_COND(!animation_set.has(p_animation2)); ERR_FAIL_COND_MSG(p_time < 0, "Blend time cannot be smaller than 0."); BlendKey bk; @@ -1462,7 +1464,7 @@ void AnimationPlayer::get_argument_options(const StringName &p_function, int p_i #endif String pf = p_function; - if (p_function == "play" || p_function == "play_backwards" || p_function == "remove_animation" || p_function == "has_animation" || p_function == "queue") { + if (p_idx == 0 && (p_function == "play" || p_function == "play_backwards" || p_function == "remove_animation" || p_function == "has_animation" || p_function == "queue")) { List<StringName> al; get_animation_list(&al); for (List<StringName>::Element *E = al.front(); E; E = E->next()) { diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index d8229b5f43..6fef44481a 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -271,6 +271,11 @@ BaseButton::DrawMode BaseButton::get_draw_mode() const { } void BaseButton::set_toggle_mode(bool p_on) { + // Make sure to set 'pressed' to false if we are not in toggle mode + if (!p_on) { + set_pressed(false); + } + toggle_mode = p_on; } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 97daeceda9..2cdee4641e 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -1173,7 +1173,17 @@ Rect2 Control::get_parent_anchorable_rect() const { if (data.parent_canvas_item) { parent_rect = data.parent_canvas_item->get_anchorable_rect(); } else { +#ifdef TOOLS_ENABLED + Node *edited_root = get_tree()->get_edited_scene_root(); + if (edited_root && (this == edited_root || edited_root->is_a_parent_of(this))) { + parent_rect.size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height")); + } else { + parent_rect = get_viewport()->get_visible_rect(); + } + +#else parent_rect = get_viewport()->get_visible_rect(); +#endif } return parent_rect; diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index c6897fc684..faef979090 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -51,7 +51,9 @@ void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) { } void AcceptDialog::_parent_focused() { - _cancel_pressed(); + if (!is_exclusive()) { + _cancel_pressed(); + } } void AcceptDialog::_notification(int p_what) { @@ -295,6 +297,8 @@ AcceptDialog::AcceptDialog() { set_wrap_controls(true); set_visible(false); set_transient(true); + set_exclusive(true); + set_clamp_to_embedder(true); bg = memnew(Panel); add_child(bg); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 41ca6458af..1e0d3d9f7b 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -604,7 +604,7 @@ void FileDialog::set_current_file(const String &p_file) { file->set_text(p_file); update_dir(); invalidate(); - int lp = p_file.find_last("."); + int lp = p_file.rfind("."); if (lp != -1) { file->select(0, lp); if (file->is_inside_tree() && !get_tree()->is_node_being_edited(file)) { @@ -617,7 +617,7 @@ void FileDialog::set_current_path(const String &p_path) { if (!p_path.size()) { return; } - int pos = MAX(p_path.find_last("/"), p_path.find_last("\\")); + int pos = MAX(p_path.rfind("/"), p_path.rfind("\\")); if (pos == -1) { set_current_file(p_path); } else { diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index b6a96238dc..01b54ddaa8 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -503,9 +503,7 @@ void GraphNode::_connpos_update() { } } - if (vofs > 0) { - vofs += sep; - } + vofs += sep; vofs += size.y; idx++; } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index ba55927980..27c2c70708 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -51,7 +51,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (b.is_valid()) { if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) { - menu->set_position(get_global_transform().xform(get_local_mouse_position())); + menu->set_position(get_screen_transform().xform(get_local_mouse_position())); menu->set_size(Vector2(1, 1)); //menu->set_scale(get_global_transform().get_scale()); menu->popup(); @@ -688,12 +688,12 @@ void LineEdit::_notification(int p_what) { update_placeholder_width(); update(); } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { window_has_focus = true; draw_caret = true; update(); } break; - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { window_has_focus = false; draw_caret = false; update(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 5ae27081ea..22e5bd55f3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -256,7 +256,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & lh = line < l.height_caches.size() ? l.height_caches[line] : 1; \ line_ascent = line < l.ascent_caches.size() ? l.ascent_caches[line] : 1; \ line_descent = line < l.descent_caches.size() ? l.descent_caches[line] : 1; \ - if (p_mode == PROCESS_DRAW) { \ + if ((p_mode == PROCESS_DRAW) && (align != ALIGN_FILL)) { \ if (line < l.offset_caches.size()) { \ wofs = l.offset_caches[line]; \ } \ diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index c7fc8dbe43..3860ce61e9 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -603,12 +603,12 @@ void TextEdit::_notification(int p_what) { _update_wrap_at(); syntax_highlighting_cache.clear(); } break; - case NOTIFICATION_WM_FOCUS_IN: { + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { window_has_focus = true; draw_caret = true; update(); } break; - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { window_has_focus = false; draw_caret = false; update(); diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 6e86f0f299..4187d77083 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -166,9 +166,11 @@ void TextureButton::_notification(int p_what) { } break; } + Point2 ofs; + Size2 size; + if (texdraw.is_valid()) { - Point2 ofs; - Size2 size = texdraw->get_size(); + size = texdraw->get_size(); _texture_region = Rect2(Point2(), texdraw->get_size()); _tile = false; if (expand) { @@ -218,17 +220,21 @@ void TextureButton::_notification(int p_what) { } _position_rect = Rect2(ofs, size); + + size.width *= hflip ? -1.0f : 1.0f; + size.height *= vflip ? -1.0f : 1.0f; + if (_tile) { - draw_texture_rect(texdraw, _position_rect, _tile); + draw_texture_rect(texdraw, Rect2(ofs, size), _tile); } else { - draw_texture_rect_region(texdraw, _position_rect, _texture_region); + draw_texture_rect_region(texdraw, Rect2(ofs, size), _texture_region); } } else { _position_rect = Rect2(); } if (has_focus() && focused.is_valid()) { - draw_texture_rect(focused, _position_rect, false); + draw_texture_rect(focused, Rect2(ofs, size), false); }; } break; } @@ -243,6 +249,10 @@ void TextureButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_click_mask", "mask"), &TextureButton::set_click_mask); ClassDB::bind_method(D_METHOD("set_expand", "p_expand"), &TextureButton::set_expand); ClassDB::bind_method(D_METHOD("set_stretch_mode", "p_mode"), &TextureButton::set_stretch_mode); + ClassDB::bind_method(D_METHOD("set_flip_h", "enable"), &TextureButton::set_flip_h); + ClassDB::bind_method(D_METHOD("is_flipped_h"), &TextureButton::is_flipped_h); + ClassDB::bind_method(D_METHOD("set_flip_v", "enable"), &TextureButton::set_flip_v); + ClassDB::bind_method(D_METHOD("is_flipped_v"), &TextureButton::is_flipped_v); ClassDB::bind_method(D_METHOD("get_normal_texture"), &TextureButton::get_normal_texture); ClassDB::bind_method(D_METHOD("get_pressed_texture"), &TextureButton::get_pressed_texture); @@ -262,6 +272,8 @@ void TextureButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand"); ADD_PROPERTY(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_flip_h", "is_flipped_h"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_v", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_flip_v", "is_flipped_v"); BIND_ENUM_CONSTANT(STRETCH_SCALE); BIND_ENUM_CONSTANT(STRETCH_TILE); @@ -345,9 +357,29 @@ TextureButton::StretchMode TextureButton::get_stretch_mode() const { return stretch_mode; } +void TextureButton::set_flip_h(bool p_flip) { + hflip = p_flip; + update(); +} + +bool TextureButton::is_flipped_h() const { + return hflip; +} + +void TextureButton::set_flip_v(bool p_flip) { + vflip = p_flip; + update(); +} + +bool TextureButton::is_flipped_v() const { + return vflip; +} + TextureButton::TextureButton() { expand = false; stretch_mode = STRETCH_SCALE; + hflip = false; + vflip = false; _texture_region = Rect2(); _position_rect = Rect2(); diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index a1e66203d3..bfd3d40db6 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -61,6 +61,9 @@ private: Rect2 _position_rect; bool _tile; + bool hflip; + bool vflip; + protected: virtual Size2 get_minimum_size() const; virtual bool has_point(const Point2 &p_point) const; @@ -88,6 +91,12 @@ public: void set_stretch_mode(StretchMode p_stretch_mode); StretchMode get_stretch_mode() const; + void set_flip_h(bool p_flip); + bool is_flipped_h() const; + + void set_flip_v(bool p_flip); + bool is_flipped_v() const; + TextureButton(); }; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 7b9db7c081..47761d724e 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1786,7 +1786,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool case TreeItem::CELL_MODE_STRING: { //nothing in particular - if (select_mode == SELECT_MULTI && (get_tree()->get_event_count() == focus_in_id || !already_cursor)) { + if (select_mode == SELECT_MULTI && (get_viewport()->get_processed_events_count() == focus_in_id || !already_cursor)) { bring_up_editor = false; } @@ -1861,7 +1861,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool } else { editor_text = String::num(p_item->cells[col].val, Math::range_step_decimals(p_item->cells[col].step)); - if (select_mode == SELECT_MULTI && get_tree()->get_event_count() == focus_in_id) { + if (select_mode == SELECT_MULTI && get_viewport()->get_processed_events_count() == focus_in_id) { bring_up_editor = false; } } @@ -2787,7 +2787,7 @@ int Tree::_get_title_button_height() const { void Tree::_notification(int p_what) { if (p_what == NOTIFICATION_FOCUS_ENTER) { - focus_in_id = get_tree()->get_event_count(); + focus_in_id = get_viewport()->get_processed_events_count(); } if (p_what == NOTIFICATION_MOUSE_EXIT) { if (cache.hover_type != Cache::CLICK_NONE) { @@ -3410,7 +3410,7 @@ void Tree::scroll_to_item(TreeItem *p_item) { const Rect2 r = get_item_rect(p_item); - if (r.position.y < v_scroll->get_value()) { + if (r.position.y <= v_scroll->get_value()) { v_scroll->set_value(r.position.y); } else if (r.position.y + r.size.y + 2 * cache.vseparation > v_scroll->get_value() + get_size().y) { v_scroll->set_value(r.position.y + r.size.y + 2 * cache.vseparation - get_size().y); @@ -3623,6 +3623,47 @@ TreeItem *Tree::get_item_at_position(const Point2 &p_pos) const { return nullptr; } +int Tree::get_button_id_at_position(const Point2 &p_pos) const { + if (root) { + Point2 pos = p_pos; + pos -= cache.bg->get_offset(); + pos.y -= _get_title_button_height(); + if (pos.y < 0) { + return -1; + } + + if (h_scroll->is_visible_in_tree()) { + pos.x += h_scroll->get_value(); + } + if (v_scroll->is_visible_in_tree()) { + pos.y += v_scroll->get_value(); + } + + int col, h, section; + TreeItem *it = _find_item_at_pos(root, pos, col, h, section); + + if (it) { + const TreeItem::Cell &c = it->cells[col]; + int col_width = get_column_width(col); + + for (int i = 0; i < col; i++) { + pos.x -= get_column_width(i); + } + + for (int j = c.buttons.size() - 1; j >= 0; j--) { + Ref<Texture2D> b = c.buttons[j].texture; + Size2 size = b->get_size() + cache.button_pressed->get_minimum_size(); + if (pos.x > col_width - size.width) { + return c.buttons[j].id; + } + col_width -= size.width; + } + } + } + + return -1; +} + String Tree::get_tooltip(const Point2 &p_pos) const { if (root) { Point2 pos = p_pos; @@ -3839,7 +3880,7 @@ Tree::Tree() { add_child(popup_menu); // popup_menu->set_as_toplevel(true); - popup_editor = memnew(PopupPanel); + popup_editor = memnew(Popup); popup_editor->set_wrap_controls(true); add_child(popup_editor); popup_editor_vb = memnew(VBoxContainer); diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 46842e78a0..cfdc307d03 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -359,11 +359,11 @@ private: VBoxContainer *popup_editor_vb; - PopupPanel *popup_editor; + Popup *popup_editor; LineEdit *text_editor; HSlider *value_editor; bool updating_value_editor; - int64_t focus_in_id; + uint64_t focus_in_id; PopupMenu *popup_menu; Vector<ColumnInfo> columns; @@ -535,6 +535,7 @@ public: TreeItem *get_item_at_position(const Point2 &p_pos) const; int get_column_at_position(const Point2 &p_pos) const; int get_drop_section_at_position(const Point2 &p_pos) const; + int get_button_id_at_position(const Point2 &p_pos) const; void clear(); diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index 881df06d8f..e118cb0d8d 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -201,10 +201,9 @@ bool VideoPlayer::has_expand() const { void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) { stop(); + AudioServer::get_singleton()->lock(); mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); - AudioServer::get_singleton()->unlock(); - stream = p_stream; if (stream.is_valid()) { stream->set_audio_track(audio_track); @@ -212,6 +211,7 @@ void VideoPlayer::set_stream(const Ref<VideoStream> &p_stream) { } else { playback = Ref<VideoStreamPlayback>(); } + AudioServer::get_singleton()->unlock(); if (!playback.is_null()) { playback->set_loop(loops); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 721f573f39..d1bf038b8d 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -1174,7 +1174,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_mesh", "mesh", "texture", "normal_map", "specular_map", "specular_shininess", "transform", "modulate", "texture_filter", "texture_repeat"), &CanvasItem::draw_mesh, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE)); ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture", "normal_map", "specular_map", "specular_shininess", "texture_filter", "texture_repeat"), &CanvasItem::draw_multimesh, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(TEXTURE_FILTER_PARENT_NODE), DEFVAL(TEXTURE_REPEAT_PARENT_NODE)); - ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform); + ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform, DEFVAL(0.0), DEFVAL(Size2(1.0, 1.0))); ClassDB::bind_method(D_METHOD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix); ClassDB::bind_method(D_METHOD("get_transform"), &CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("get_global_transform"), &CanvasItem::get_global_transform); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 31edd424a1..918610ac1e 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -348,7 +348,7 @@ public: void draw_string(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate = Color(1, 1, 1), int p_clip_w = -1); float draw_char(const Ref<Font> &p_font, const Point2 &p_pos, const String &p_char, const String &p_next = "", const Color &p_modulate = Color(1, 1, 1)); - void draw_set_transform(const Point2 &p_offset, float p_rot, const Size2 &p_scale); + void draw_set_transform(const Point2 &p_offset, float p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0)); void draw_set_transform_matrix(const Transform2D &p_matrix); static CanvasItem *get_current_item_drawn(); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 1bf828a03b..88f9730f78 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2857,8 +2857,8 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER); BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT); - BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN); - BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT); + BIND_CONSTANT(NOTIFICATION_WM_WINDOW_FOCUS_IN); + BIND_CONSTANT(NOTIFICATION_WM_WINDOW_FOCUS_OUT); BIND_CONSTANT(NOTIFICATION_WM_CLOSE_REQUEST); BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST); BIND_CONSTANT(NOTIFICATION_WM_SIZE_CHANGED); @@ -2867,8 +2867,10 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_WM_ABOUT); BIND_CONSTANT(NOTIFICATION_CRASH); BIND_CONSTANT(NOTIFICATION_OS_IME_UPDATE); - BIND_CONSTANT(NOTIFICATION_APP_RESUMED); - BIND_CONSTANT(NOTIFICATION_APP_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_RESUMED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_PAUSED); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_IN); + BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT); BIND_ENUM_CONSTANT(PAUSE_MODE_INHERIT); BIND_ENUM_CONSTANT(PAUSE_MODE_STOP); diff --git a/scene/main/node.h b/scene/main/node.h index 7595aabd9a..c3972e2d8e 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -243,8 +243,8 @@ public: NOTIFICATION_WM_MOUSE_ENTER = 1002, NOTIFICATION_WM_MOUSE_EXIT = 1003, - NOTIFICATION_WM_FOCUS_IN = 1004, - NOTIFICATION_WM_FOCUS_OUT = 1005, + NOTIFICATION_WM_WINDOW_FOCUS_IN = 1004, + NOTIFICATION_WM_WINDOW_FOCUS_OUT = 1005, NOTIFICATION_WM_CLOSE_REQUEST = 1006, NOTIFICATION_WM_GO_BACK_REQUEST = 1007, NOTIFICATION_WM_SIZE_CHANGED = 1008, @@ -255,8 +255,10 @@ public: NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT, NOTIFICATION_CRASH = MainLoop::NOTIFICATION_CRASH, NOTIFICATION_OS_IME_UPDATE = MainLoop::NOTIFICATION_OS_IME_UPDATE, - NOTIFICATION_APP_RESUMED = MainLoop::NOTIFICATION_APP_RESUMED, - NOTIFICATION_APP_PAUSED = MainLoop::NOTIFICATION_APP_PAUSED + NOTIFICATION_APPLICATION_RESUMED = MainLoop::NOTIFICATION_APPLICATION_RESUMED, + NOTIFICATION_APPLICATION_PAUSED = MainLoop::NOTIFICATION_APPLICATION_PAUSED, + NOTIFICATION_APPLICATION_FOCUS_IN = MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN, + NOTIFICATION_APPLICATION_FOCUS_OUT = MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT }; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 3c3c7533a3..d6159e089b 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -587,9 +587,11 @@ void SceneTree::_notification(int p_notification) { case NOTIFICATION_OS_IME_UPDATE: case NOTIFICATION_WM_ABOUT: case NOTIFICATION_CRASH: - case NOTIFICATION_APP_RESUMED: - case NOTIFICATION_APP_PAUSED: { - get_root()->propagate_notification(p_notification); + case NOTIFICATION_APPLICATION_RESUMED: + case NOTIFICATION_APPLICATION_PAUSED: + case NOTIFICATION_APPLICATION_FOCUS_IN: + case NOTIFICATION_APPLICATION_FOCUS_OUT: { + get_root()->propagate_notification(p_notification); //pass these to nodes, since they are mirrored } break; default: @@ -937,10 +939,6 @@ int64_t SceneTree::get_frame() const { return current_frame; } -int64_t SceneTree::get_event_count() const { - return current_event; -} - Array SceneTree::_get_nodes_in_group(const StringName &p_group) { Array ret; Map<StringName, Group>::Element *E = group_map.find(p_group); @@ -1360,7 +1358,6 @@ SceneTree::SceneTree() { root = nullptr; pause = false; current_frame = 0; - current_event = 0; tree_changed_name = "tree_changed"; node_added_name = "node_added"; node_removed_name = "node_removed"; diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 57b6b4dcfa..bea29c7605 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -110,7 +110,6 @@ private: StringName node_renamed_name; int64_t current_frame; - int64_t current_event; int node_count; #ifdef TOOLS_ENABLED @@ -300,7 +299,6 @@ public: int get_collision_debug_contact_count() { return collision_debug_contacts; } int64_t get_frame() const; - int64_t get_event_count() const; int get_node_count() const; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 8544d67ecc..1c259b7d32 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -815,7 +815,7 @@ void Viewport::_notification(int p_what) { } break; case NOTIFICATION_WM_MOUSE_EXIT: - case NOTIFICATION_WM_FOCUS_OUT: { + case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { _drop_physics_mouseover(); if (gui.mouse_focus && !gui.forced_mouse_focus) { @@ -2083,7 +2083,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { Control *c = over; Vector2 cpos = pos; while (c) { - cursor_shape = c->get_cursor_shape(cpos); + if (gui.mouse_focus_mask != 0 || c->has_point(cpos)) { + cursor_shape = c->get_cursor_shape(cpos); + } else { + cursor_shape = Control::CURSOR_ARROW; + } cpos = c->get_transform().xform(cpos); if (cursor_shape != Control::CURSOR_ARROW) { break; @@ -2450,6 +2454,22 @@ void Viewport::_gui_remove_control(Control *p_control) { } } +Window *Viewport::get_base_window() const { + Viewport *v = const_cast<Viewport *>(this); + Window *w = Object::cast_to<Window>(v); + while (!w) { + v = v->get_parent_viewport(); + w = Object::cast_to<Window>(v); + } + + return w; +} +void Viewport::_gui_remove_focus_for_window(Node *p_window) { + if (get_base_window() == p_window) { + _gui_remove_focus(); + } +} + void Viewport::_gui_remove_focus() { if (gui.key_focus) { Node *f = gui.key_focus; @@ -2467,7 +2487,7 @@ void Viewport::_gui_control_grab_focus(Control *p_control) { if (gui.key_focus && gui.key_focus == p_control) { return; } - get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus"); + get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus_for_window", (Node *)get_base_window()); gui.key_focus = p_control; emit_signal("gui_focus_changed", p_control); p_control->notification(Control::NOTIFICATION_FOCUS_ENTER); @@ -2685,6 +2705,27 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) { if (gui.subwindow_drag == SUB_WINDOW_DRAG_MOVE) { Vector2 diff = mm->get_position() - gui.subwindow_drag_from; Rect2i new_rect(gui.subwindow_drag_pos + diff, gui.subwindow_focused->get_size()); + + if (gui.subwindow_focused->is_clamped_to_embedder()) { + Size2i limit = get_visible_rect().size; + if (new_rect.position.x + new_rect.size.x > limit.x) { + new_rect.position.x = limit.x - new_rect.size.x; + } + if (new_rect.position.y + new_rect.size.y > limit.y) { + new_rect.position.y = limit.y - new_rect.size.y; + } + + if (new_rect.position.x < 0) { + new_rect.position.x = 0; + } + + int title_height = gui.subwindow_focused->get_flag(Window::FLAG_BORDERLESS) ? 0 : gui.subwindow_focused->get_theme_constant("title_height"); + + if (new_rect.position.y < title_height) { + new_rect.position.y = title_height; + } + } + gui.subwindow_focused->_rect_changed_callback(new_rect); } if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) { @@ -2913,6 +2954,10 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) { return; } + if (!_can_consume_input_events()) { + return; + } + if (!is_input_handled()) { get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input } @@ -2920,13 +2965,15 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) { if (!is_input_handled()) { _gui_input_event(ev); } + + event_count++; //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",ev); //special one for GUI, as controls use their own process check } void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) { ERR_FAIL_COND(!is_inside_tree()); - if (disable_input) { + if (disable_input || !_can_consume_input_events()) { return; } @@ -3301,8 +3348,7 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input); ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled); - ClassDB::bind_method(D_METHOD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip); - ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus); + ClassDB::bind_method(D_METHOD("_gui_remove_focus_for_window"), &Viewport::_gui_remove_focus_for_window); ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus); ClassDB::bind_method(D_METHOD("set_shadow_atlas_size", "size"), &Viewport::set_shadow_atlas_size); @@ -3404,9 +3450,11 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE); BIND_ENUM_CONSTANT(DEBUG_DRAW_SSAO); - BIND_ENUM_CONSTANT(DEBUG_DRAW_ROUGHNESS_LIMITER); BIND_ENUM_CONSTANT(DEBUG_DRAW_PSSM_SPLITS); BIND_ENUM_CONSTANT(DEBUG_DRAW_DECAL_ATLAS); + BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI); + BIND_ENUM_CONSTANT(DEBUG_DRAW_SDFGI_PROBES); + BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_BUFFER); BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST); BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 4536b558f9..09ef4354c5 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -137,9 +137,11 @@ public: DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, DEBUG_DRAW_SCENE_LUMINANCE, DEBUG_DRAW_SSAO, - DEBUG_DRAW_ROUGHNESS_LIMITER, DEBUG_DRAW_PSSM_SPLITS, - DEBUG_DRAW_DECAL_ATLAS + DEBUG_DRAW_DECAL_ATLAS, + DEBUG_DRAW_SDFGI, + DEBUG_DRAW_SDFGI_PROBES, + DEBUG_DRAW_GI_BUFFER, }; enum DefaultCanvasItemTextureFilter { @@ -390,6 +392,7 @@ private: void _gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control); void _gui_set_drag_preview(Control *p_base, Control *p_control); + void _gui_remove_focus_for_window(Node *p_window); void _gui_remove_focus(); void _gui_unfocus_control(Control *p_control); bool _gui_control_has_focus(const Control *p_control); @@ -439,6 +442,9 @@ private: bool _sub_windows_forward_input(const Ref<InputEvent> &p_event); SubWindowResize _sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point); + virtual bool _can_consume_input_events() const { return true; } + uint64_t event_count = 0; + protected: void _set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated); @@ -451,6 +457,8 @@ protected: virtual void _validate_property(PropertyInfo &property) const; public: + uint64_t get_processed_events_count() const { return event_count; } + Listener3D *get_listener() const; Camera3D *get_camera() const; @@ -568,6 +576,7 @@ public: bool is_embedding_subwindows() const; Viewport *get_parent_viewport() const; + Window *get_base_window() const; void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index a9be8a1eff..48540b7bc9 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -309,6 +309,7 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) { case DisplayServer::WINDOW_EVENT_MOUSE_ENTER: { _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_ENTER); emit_signal("mouse_entered"); + DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_ARROW); //restore cursor shape } break; case DisplayServer::WINDOW_EVENT_MOUSE_EXIT: { _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_EXIT); @@ -316,13 +317,13 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) { } break; case DisplayServer::WINDOW_EVENT_FOCUS_IN: { focused = true; - _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_IN); + _propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_IN); emit_signal("focus_entered"); } break; case DisplayServer::WINDOW_EVENT_FOCUS_OUT: { focused = false; - _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_OUT); + _propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_OUT); emit_signal("focus_exited"); } break; case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: { @@ -398,6 +399,18 @@ void Window::set_visible(bool p_visible) { emit_signal(SceneStringNames::get_singleton()->visibility_changed); RS::get_singleton()->viewport_set_active(get_viewport_rid(), visible); + + //update transient exclusive + if (transient_parent) { + if (exclusive && visible) { + ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child."); + transient_parent->exclusive_child = this; + } else { + if (transient_parent->exclusive_child == this) { + transient_parent->exclusive_child = nullptr; + } + } + } } void Window::_clear_transient() { @@ -612,26 +625,25 @@ void Window::_update_viewport_size() { // Already handled above //_update_font_oversampling(1.0); } break; - case CONTENT_SCALE_MODE_OBJECTS: { + case CONTENT_SCALE_MODE_CANVAS_ITEMS: { final_size = screen_size; final_size_override = viewport_size; attach_to_screen_rect = Rect2(margin, screen_size); font_oversampling = screen_size.x / viewport_size.x; + + Size2 scale = Vector2(screen_size) / Vector2(final_size_override); + stretch_transform.scale(scale); + } break; - case CONTENT_SCALE_MODE_PIXELS: { + case CONTENT_SCALE_MODE_VIEWPORT: { final_size = viewport_size; attach_to_screen_rect = Rect2(margin, screen_size); } break; } - - Size2 scale = size / (Vector2(final_size) + margin * 2); - stretch_transform.scale(scale); - stretch_transform.elements[2] = margin * scale; } bool allocate = is_inside_tree() && visible && (window_id != DisplayServer::INVALID_WINDOW_ID || embedder != nullptr); - _set_size(final_size, final_size_override, attach_to_screen_rect, stretch_transform, allocate); if (window_id != DisplayServer::INVALID_WINDOW_ID) { @@ -862,6 +874,10 @@ void Window::child_controls_changed() { call_deferred("_update_child_controls"); } +bool Window::_can_consume_input_events() const { + return exclusive_child == nullptr; +} + void Window::_window_input(const Ref<InputEvent> &p_ev) { if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev))) { return; //avoid joy input on editor @@ -878,10 +894,13 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) { if (exclusive_child != nullptr) { exclusive_child->grab_focus(); - return; //has an exclusive child, can't get events until child is closed + if (!is_embedding_subwindows()) { //not embedding, no need for event + return; + } } emit_signal(SceneStringNames::get_singleton()->window_input, p_ev); + input(p_ev); if (!is_input_handled()) { unhandled_input(p_ev); @@ -1232,6 +1251,14 @@ Rect2i Window::get_parent_rect() const { } } +void Window::set_clamp_to_embedder(bool p_enable) { + clamp_to_embedder = p_enable; +} + +bool Window::is_clamped_to_embedder() const { + return clamp_to_embedder; +} + void Window::_bind_methods() { ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title); ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title); @@ -1345,7 +1372,7 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size"), "set_max_size", "get_max_size"); ADD_GROUP("Content Scale", "content_scale_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Object,Pixels"), "set_content_scale_mode", "get_content_scale_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,CanvasItems,Viewport"), "set_content_scale_mode", "get_content_scale_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect"); ADD_GROUP("Theme", ""); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme"); @@ -1376,8 +1403,8 @@ void Window::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED); - BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_OBJECTS); - BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_PIXELS); + BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_CANVAS_ITEMS); + BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_VIEWPORT); BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_IGNORE); BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP); diff --git a/scene/main/window.h b/scene/main/window.h index adaa5ca3be..c8c02b8984 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -57,8 +57,8 @@ public: enum ContentScaleMode { CONTENT_SCALE_MODE_DISABLED, - CONTENT_SCALE_MODE_OBJECTS, - CONTENT_SCALE_MODE_PIXELS, + CONTENT_SCALE_MODE_CANVAS_ITEMS, + CONTENT_SCALE_MODE_VIEWPORT, }; enum ContentScaleAspect { @@ -92,6 +92,7 @@ private: bool exclusive = false; bool wrap_controls = false; bool updating_child_controls = false; + bool clamp_to_embedder = false; void _update_child_controls(); @@ -130,10 +131,10 @@ private: void _window_drop_files(const Vector<String> &p_files); void _rect_changed_callback(const Rect2i &p_callback); void _event_callback(DisplayServer::WindowEvent p_event); + virtual bool _can_consume_input_events() const; protected: Viewport *_get_embedder() const; - virtual Rect2i _popup_adjust_rect() const { return Rect2i(); } virtual void _post_popup() {} @@ -195,6 +196,9 @@ public: void set_exclusive(bool p_exclusive); bool is_exclusive() const; + void set_clamp_to_embedder(bool p_enable); + bool is_clamped_to_embedder() const; + bool can_draw() const; void set_ime_active(bool p_active); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 54112ef2bd..86ea0406e1 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -131,6 +131,7 @@ #include "scene/resources/audio_stream_sample.h" #include "scene/resources/bit_map.h" #include "scene/resources/box_shape_3d.h" +#include "scene/resources/camera_effects.h" #include "scene/resources/capsule_shape_2d.h" #include "scene/resources/capsule_shape_3d.h" #include "scene/resources/circle_shape_2d.h" diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 014b773298..479d97aadc 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2577,7 +2577,10 @@ void Animation::copy_track(int p_track, Ref<Animation> p_to_animation) { p_to_animation->track_set_enabled(dst_track, track_is_enabled(p_track)); p_to_animation->track_set_interpolation_type(dst_track, track_get_interpolation_type(p_track)); p_to_animation->track_set_interpolation_loop_wrap(dst_track, track_get_interpolation_loop_wrap(p_track)); - p_to_animation->value_track_set_update_mode(dst_track, value_track_get_update_mode(p_track)); + if (track_get_type(p_track) == TYPE_VALUE) { + p_to_animation->value_track_set_update_mode(dst_track, value_track_get_update_mode(p_track)); + } + for (int i = 0; i < track_get_key_count(p_track); i++) { p_to_animation->track_insert_key(dst_track, track_get_key_time(p_track, i), track_get_key_value(p_track, i), track_get_key_transition(p_track, i)); } diff --git a/scene/resources/camera_effects.cpp b/scene/resources/camera_effects.cpp new file mode 100644 index 0000000000..6b6ed51ed0 --- /dev/null +++ b/scene/resources/camera_effects.cpp @@ -0,0 +1,197 @@ +/*************************************************************************/ +/* camera_effects.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 "camera_effects.h" + +#include "servers/rendering_server.h" + +RID CameraEffects::get_rid() const { + return camera_effects; +} + +// DOF blur + +void CameraEffects::set_dof_blur_far_enabled(bool p_enabled) { + dof_blur_far_enabled = p_enabled; + _update_dof_blur(); + _change_notify(); +} + +bool CameraEffects::is_dof_blur_far_enabled() const { + return dof_blur_far_enabled; +} + +void CameraEffects::set_dof_blur_far_distance(float p_distance) { + dof_blur_far_distance = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_far_distance() const { + return dof_blur_far_distance; +} + +void CameraEffects::set_dof_blur_far_transition(float p_distance) { + dof_blur_far_transition = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_far_transition() const { + return dof_blur_far_transition; +} + +void CameraEffects::set_dof_blur_near_enabled(bool p_enabled) { + dof_blur_near_enabled = p_enabled; + _update_dof_blur(); + _change_notify(); +} + +bool CameraEffects::is_dof_blur_near_enabled() const { + return dof_blur_near_enabled; +} + +void CameraEffects::set_dof_blur_near_distance(float p_distance) { + dof_blur_near_distance = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_near_distance() const { + return dof_blur_near_distance; +} + +void CameraEffects::set_dof_blur_near_transition(float p_distance) { + dof_blur_near_transition = p_distance; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_near_transition() const { + return dof_blur_near_transition; +} + +void CameraEffects::set_dof_blur_amount(float p_amount) { + dof_blur_amount = p_amount; + _update_dof_blur(); +} + +float CameraEffects::get_dof_blur_amount() const { + return dof_blur_amount; +} + +void CameraEffects::_update_dof_blur() { + RS::get_singleton()->camera_effects_set_dof_blur( + camera_effects, + dof_blur_far_enabled, + dof_blur_far_distance, + dof_blur_far_transition, + dof_blur_near_enabled, + dof_blur_near_distance, + dof_blur_near_transition, + dof_blur_amount); +} + +// Custom exposure + +void CameraEffects::set_override_exposure_enabled(bool p_enabled) { + override_exposure_enabled = p_enabled; + _update_override_exposure(); +} + +bool CameraEffects::is_override_exposure_enabled() const { + return override_exposure_enabled; +} + +void CameraEffects::set_override_exposure(float p_exposure) { + override_exposure = p_exposure; + _update_override_exposure(); +} + +float CameraEffects::get_override_exposure() const { + return override_exposure; +} + +void CameraEffects::_update_override_exposure() { + RS::get_singleton()->camera_effects_set_custom_exposure( + camera_effects, + override_exposure_enabled, + override_exposure); +} + +// Private methods, constructor and destructor + +void CameraEffects::_bind_methods() { + // DOF blur + + ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &CameraEffects::set_dof_blur_far_enabled); + ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &CameraEffects::is_dof_blur_far_enabled); + ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "distance"), &CameraEffects::set_dof_blur_far_distance); + ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &CameraEffects::get_dof_blur_far_distance); + ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "distance"), &CameraEffects::set_dof_blur_far_transition); + ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &CameraEffects::get_dof_blur_far_transition); + + ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &CameraEffects::set_dof_blur_near_enabled); + ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &CameraEffects::is_dof_blur_near_enabled); + ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "distance"), &CameraEffects::set_dof_blur_near_distance); + ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &CameraEffects::get_dof_blur_near_distance); + ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "distance"), &CameraEffects::set_dof_blur_near_transition); + ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &CameraEffects::get_dof_blur_near_transition); + + ClassDB::bind_method(D_METHOD("set_dof_blur_amount", "amount"), &CameraEffects::set_dof_blur_amount); + ClassDB::bind_method(D_METHOD("get_dof_blur_amount"), &CameraEffects::get_dof_blur_amount); + + ADD_GROUP("DOF Blur", "dof_blur_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_distance", "get_dof_blur_far_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_transition", "get_dof_blur_far_transition"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_distance", "get_dof_blur_near_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_transition", "get_dof_blur_near_transition"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount"); + + // Override exposure + + ClassDB::bind_method(D_METHOD("set_override_exposure_enabled", "enabled"), &CameraEffects::set_override_exposure_enabled); + ClassDB::bind_method(D_METHOD("is_override_exposure_enabled"), &CameraEffects::is_override_exposure_enabled); + ClassDB::bind_method(D_METHOD("set_override_exposure", "exposure"), &CameraEffects::set_override_exposure); + ClassDB::bind_method(D_METHOD("get_override_exposure"), &CameraEffects::get_override_exposure); + + ADD_GROUP("Override Exposure", "override_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_exposure_enabled"), "set_override_exposure_enabled", "is_override_exposure_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "override_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_override_exposure", "get_override_exposure"); +} + +CameraEffects::CameraEffects() { + camera_effects = RS::get_singleton()->camera_effects_create(); + + _update_dof_blur(); + _update_override_exposure(); +} + +CameraEffects::~CameraEffects() { + RS::get_singleton()->free(camera_effects); +} diff --git a/scene/resources/camera_effects.h b/scene/resources/camera_effects.h new file mode 100644 index 0000000000..6b216e3296 --- /dev/null +++ b/scene/resources/camera_effects.h @@ -0,0 +1,94 @@ +/*************************************************************************/ +/* camera_effects.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 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 CAMERA_EFFECTS_H +#define CAMERA_EFFECTS_H + +#include "core/resource.h" +#include "core/rid.h" + +class CameraEffects : public Resource { + GDCLASS(CameraEffects, Resource); + +private: + RID camera_effects; + + // DOF blur + bool dof_blur_far_enabled = false; + float dof_blur_far_distance = 10; + float dof_blur_far_transition = 5; + + bool dof_blur_near_enabled = false; + float dof_blur_near_distance = 2; + float dof_blur_near_transition = 1; + + float dof_blur_amount = 0.1; + void _update_dof_blur(); + + // Override exposure + bool override_exposure_enabled = false; + float override_exposure = 1.0; + void _update_override_exposure(); + +protected: + static void _bind_methods(); + +public: + virtual RID get_rid() const; + + // DOF blur + void set_dof_blur_far_enabled(bool p_enabled); + bool is_dof_blur_far_enabled() const; + void set_dof_blur_far_distance(float p_distance); + float get_dof_blur_far_distance() const; + void set_dof_blur_far_transition(float p_distance); + float get_dof_blur_far_transition() const; + + void set_dof_blur_near_enabled(bool p_enabled); + bool is_dof_blur_near_enabled() const; + void set_dof_blur_near_distance(float p_distance); + float get_dof_blur_near_distance() const; + void set_dof_blur_near_transition(float p_distance); + float get_dof_blur_near_transition() const; + + void set_dof_blur_amount(float p_amount); + float get_dof_blur_amount() const; + + // Override exposure + void set_override_exposure_enabled(bool p_enabled); + bool is_override_exposure_enabled() const; + void set_override_exposure(float p_exposure); + float get_override_exposure() const; + + CameraEffects(); + ~CameraEffects(); +}; + +#endif // CAMERA_EFFECTS_H diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 80ee0c148d..94629a77b9 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "environment.h" + #include "core/project_settings.h" #include "servers/rendering_server.h" #include "texture.h" @@ -37,136 +38,159 @@ RID Environment::get_rid() const { return environment; } +// Background + void Environment::set_background(BGMode p_bg) { bg_mode = p_bg; RS::get_singleton()->environment_set_background(environment, RS::EnvironmentBG(p_bg)); _change_notify(); } +Environment::BGMode Environment::get_background() const { + return bg_mode; +} + void Environment::set_sky(const Ref<Sky> &p_sky) { bg_sky = p_sky; - RID sb_rid; if (bg_sky.is_valid()) { sb_rid = bg_sky->get_rid(); } - RS::get_singleton()->environment_set_sky(environment, sb_rid); } +Ref<Sky> Environment::get_sky() const { + return bg_sky; +} + void Environment::set_sky_custom_fov(float p_scale) { bg_sky_custom_fov = p_scale; RS::get_singleton()->environment_set_sky_custom_fov(environment, p_scale); } +float Environment::get_sky_custom_fov() const { + return bg_sky_custom_fov; +} + +void Environment::set_sky_rotation(const Vector3 &p_rotation) { + bg_sky_rotation = p_rotation; + RS::get_singleton()->environment_set_sky_orientation(environment, Basis(p_rotation)); +} + +Vector3 Environment::get_sky_rotation() const { + return bg_sky_rotation; +} + void Environment::set_bg_color(const Color &p_color) { bg_color = p_color; RS::get_singleton()->environment_set_bg_color(environment, p_color); } +Color Environment::get_bg_color() const { + return bg_color; +} + void Environment::set_bg_energy(float p_energy) { bg_energy = p_energy; RS::get_singleton()->environment_set_bg_energy(environment, p_energy); } +float Environment::get_bg_energy() const { + return bg_energy; +} + void Environment::set_canvas_max_layer(int p_max_layer) { bg_canvas_max_layer = p_max_layer; RS::get_singleton()->environment_set_canvas_max_layer(environment, p_max_layer); } -void Environment::set_ambient_light_color(const Color &p_color) { - ambient_color = p_color; - RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); -} - -void Environment::set_ambient_light_energy(float p_energy) { - ambient_energy = p_energy; - RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); -} - -void Environment::set_ambient_light_sky_contribution(float p_energy) { - ambient_sky_contribution = p_energy; - RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); +int Environment::get_canvas_max_layer() const { + return bg_canvas_max_layer; } -void Environment::set_camera_feed_id(int p_camera_feed_id) { - camera_feed_id = p_camera_feed_id; +void Environment::set_camera_feed_id(int p_id) { + bg_camera_feed_id = p_id; // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 RS::get_singleton()->environment_set_camera_feed_id(environment, camera_feed_id); #endif -}; - -void Environment::set_ambient_source(AmbientSource p_source) { - ambient_source = p_source; - RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); } -Environment::AmbientSource Environment::get_ambient_source() const { - return ambient_source; +int Environment::get_camera_feed_id() const { + return bg_camera_feed_id; } -void Environment::set_reflection_source(ReflectionSource p_source) { - reflection_source = p_source; - RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); -} +// Ambient light -Environment::ReflectionSource Environment::get_reflection_source() const { - return reflection_source; +void Environment::set_ambient_light_color(const Color &p_color) { + ambient_color = p_color; + _update_ambient_light(); } -Environment::BGMode Environment::get_background() const { - return bg_mode; +Color Environment::get_ambient_light_color() const { + return ambient_color; } -Ref<Sky> Environment::get_sky() const { - return bg_sky; +void Environment::set_ambient_source(AmbientSource p_source) { + ambient_source = p_source; + _update_ambient_light(); } -float Environment::get_sky_custom_fov() const { - return bg_sky_custom_fov; +Environment::AmbientSource Environment::get_ambient_source() const { + return ambient_source; } -void Environment::set_sky_rotation(const Vector3 &p_rotation) { - sky_rotation = p_rotation; - RS::get_singleton()->environment_set_sky_orientation(environment, Basis(p_rotation)); +void Environment::set_ambient_light_energy(float p_energy) { + ambient_energy = p_energy; + _update_ambient_light(); } -Vector3 Environment::get_sky_rotation() const { - return sky_rotation; +float Environment::get_ambient_light_energy() const { + return ambient_energy; } -Color Environment::get_bg_color() const { - return bg_color; +void Environment::set_ambient_light_sky_contribution(float p_ratio) { + ambient_sky_contribution = p_ratio; + _update_ambient_light(); } -float Environment::get_bg_energy() const { - return bg_energy; +float Environment::get_ambient_light_sky_contribution() const { + return ambient_sky_contribution; } -int Environment::get_canvas_max_layer() const { - return bg_canvas_max_layer; +void Environment::set_reflection_source(ReflectionSource p_source) { + reflection_source = p_source; + _update_ambient_light(); } -Color Environment::get_ambient_light_color() const { - return ambient_color; +Environment::ReflectionSource Environment::get_reflection_source() const { + return reflection_source; } -float Environment::get_ambient_light_energy() const { - return ambient_energy; +void Environment::set_ao_color(const Color &p_color) { + ao_color = p_color; + _update_ambient_light(); } -float Environment::get_ambient_light_sky_contribution() const { - return ambient_sky_contribution; +Color Environment::get_ao_color() const { + return ao_color; } -int Environment::get_camera_feed_id() const { - return camera_feed_id; +void Environment::_update_ambient_light() { + RS::get_singleton()->environment_set_ambient_light( + environment, + ambient_color, + RS::EnvironmentAmbientSource(ambient_source), + ambient_energy, + ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), + ao_color); } +// Tonemap + void Environment::set_tonemapper(ToneMapper p_tone_mapper) { tone_mapper = p_tone_mapper; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } Environment::ToneMapper Environment::get_tonemapper() const { @@ -175,7 +199,7 @@ Environment::ToneMapper Environment::get_tonemapper() const { void Environment::set_tonemap_exposure(float p_exposure) { tonemap_exposure = p_exposure; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } float Environment::get_tonemap_exposure() const { @@ -184,44 +208,44 @@ float Environment::get_tonemap_exposure() const { void Environment::set_tonemap_white(float p_white) { tonemap_white = p_white; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } float Environment::get_tonemap_white() const { return tonemap_white; } -void Environment::set_tonemap_auto_exposure(bool p_enabled) { - tonemap_auto_exposure = p_enabled; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); +void Environment::set_tonemap_auto_exposure_enabled(bool p_enabled) { + tonemap_auto_exposure_enabled = p_enabled; + _update_tonemap(); _change_notify(); } -bool Environment::get_tonemap_auto_exposure() const { - return tonemap_auto_exposure; -} - -void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) { - tonemap_auto_exposure_max = p_auto_exposure_max; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); -} - -float Environment::get_tonemap_auto_exposure_max() const { - return tonemap_auto_exposure_max; +bool Environment::is_tonemap_auto_exposure_enabled() const { + return tonemap_auto_exposure_enabled; } void Environment::set_tonemap_auto_exposure_min(float p_auto_exposure_min) { tonemap_auto_exposure_min = p_auto_exposure_min; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } float Environment::get_tonemap_auto_exposure_min() const { return tonemap_auto_exposure_min; } +void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) { + tonemap_auto_exposure_max = p_auto_exposure_max; + _update_tonemap(); +} + +float Environment::get_tonemap_auto_exposure_max() const { + return tonemap_auto_exposure_max; +} + void Environment::set_tonemap_auto_exposure_speed(float p_auto_exposure_speed) { tonemap_auto_exposure_speed = p_auto_exposure_speed; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } float Environment::get_tonemap_auto_exposure_speed() const { @@ -230,143 +254,31 @@ float Environment::get_tonemap_auto_exposure_speed() const { void Environment::set_tonemap_auto_exposure_grey(float p_auto_exposure_grey) { tonemap_auto_exposure_grey = p_auto_exposure_grey; - RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _update_tonemap(); } float Environment::get_tonemap_auto_exposure_grey() const { return tonemap_auto_exposure_grey; } -void Environment::set_adjustment_enable(bool p_enable) { - adjustment_enabled = p_enable; - RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); - _change_notify(); -} - -bool Environment::is_adjustment_enabled() const { - return adjustment_enabled; -} - -void Environment::set_adjustment_brightness(float p_brightness) { - adjustment_brightness = p_brightness; - RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} - -float Environment::get_adjustment_brightness() const { - return adjustment_brightness; +void Environment::_update_tonemap() { + RS::get_singleton()->environment_set_tonemap( + environment, + RS::EnvironmentToneMapper(tone_mapper), + tonemap_exposure, + tonemap_white, + tonemap_auto_exposure_enabled, + tonemap_auto_exposure_min, + tonemap_auto_exposure_max, + tonemap_auto_exposure_speed, + tonemap_auto_exposure_grey); } -void Environment::set_adjustment_contrast(float p_contrast) { - adjustment_contrast = p_contrast; - RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} +// SSR -float Environment::get_adjustment_contrast() const { - return adjustment_contrast; -} - -void Environment::set_adjustment_saturation(float p_saturation) { - adjustment_saturation = p_saturation; - RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} - -float Environment::get_adjustment_saturation() const { - return adjustment_saturation; -} - -void Environment::set_adjustment_color_correction(const Ref<Texture2D> &p_ramp) { - adjustment_color_correction = p_ramp; - RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); -} - -Ref<Texture2D> Environment::get_adjustment_color_correction() const { - return adjustment_color_correction; -} - -void Environment::_validate_property(PropertyInfo &property) const { - if (property.name == "sky" || property.name == "sky_custom_fov" || property.name == "sky_rotation" || property.name == "ambient_light/sky_contribution") { - if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - } - - if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - - if (property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - - if (property.name == "background_color") { - if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - } - - if (property.name == "background_canvas_max_layer") { - if (bg_mode != BG_CANVAS) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - } - } - - if (property.name == "background_camera_feed_id") { - if (bg_mode != BG_CAMERA_FEED) { - property.usage = PROPERTY_USAGE_NOEDITOR; - } - } - - static const char *hide_prefixes[] = { - "fog_", - "auto_exposure_", - "ss_reflections_", - "ssao_", - "glow_", - "adjustment_", - nullptr - - }; - - static const char *high_end_prefixes[] = { - "auto_exposure_", - "tonemap_", - "ss_reflections_", - "ssao_", - nullptr - - }; - - const char **prefixes = hide_prefixes; - while (*prefixes) { - String prefix = String(*prefixes); - - String enabled = prefix + "enabled"; - if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - return; - } - - prefixes++; - } - - if (RenderingServer::get_singleton()->is_low_end()) { - prefixes = high_end_prefixes; - while (*prefixes) { - String prefix = String(*prefixes); - - if (property.name.begins_with(prefix)) { - property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; - return; - } - - prefixes++; - } - } -} - -void Environment::set_ssr_enabled(bool p_enable) { - ssr_enabled = p_enable; - RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance); +void Environment::set_ssr_enabled(bool p_enabled) { + ssr_enabled = p_enabled; + _update_ssr(); _change_notify(); } @@ -376,7 +288,7 @@ bool Environment::is_ssr_enabled() const { void Environment::set_ssr_max_steps(int p_steps) { ssr_max_steps = p_steps; - RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance); + _update_ssr(); } int Environment::get_ssr_max_steps() const { @@ -385,7 +297,7 @@ int Environment::get_ssr_max_steps() const { void Environment::set_ssr_fade_in(float p_fade_in) { ssr_fade_in = p_fade_in; - RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance); + _update_ssr(); } float Environment::get_ssr_fade_in() const { @@ -394,7 +306,7 @@ float Environment::get_ssr_fade_in() const { void Environment::set_ssr_fade_out(float p_fade_out) { ssr_fade_out = p_fade_out; - RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance); + _update_ssr(); } float Environment::get_ssr_fade_out() const { @@ -403,16 +315,28 @@ float Environment::get_ssr_fade_out() const { void Environment::set_ssr_depth_tolerance(float p_depth_tolerance) { ssr_depth_tolerance = p_depth_tolerance; - RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance); + _update_ssr(); } float Environment::get_ssr_depth_tolerance() const { return ssr_depth_tolerance; } -void Environment::set_ssao_enabled(bool p_enable) { - ssao_enabled = p_enable; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); +void Environment::_update_ssr() { + RS::get_singleton()->environment_set_ssr( + environment, + ssr_enabled, + ssr_max_steps, + ssr_fade_in, + ssr_fade_out, + ssr_depth_tolerance); +} + +// SSAO + +void Environment::set_ssao_enabled(bool p_enabled) { + ssao_enabled = p_enabled; + _update_ssao(); _change_notify(); } @@ -422,7 +346,7 @@ bool Environment::is_ssao_enabled() const { void Environment::set_ssao_radius(float p_radius) { ssao_radius = p_radius; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } float Environment::get_ssao_radius() const { @@ -431,7 +355,7 @@ float Environment::get_ssao_radius() const { void Environment::set_ssao_intensity(float p_intensity) { ssao_intensity = p_intensity; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } float Environment::get_ssao_intensity() const { @@ -440,7 +364,7 @@ float Environment::get_ssao_intensity() const { void Environment::set_ssao_bias(float p_bias) { ssao_bias = p_bias; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } float Environment::get_ssao_bias() const { @@ -449,7 +373,7 @@ float Environment::get_ssao_bias() const { void Environment::set_ssao_direct_light_affect(float p_direct_light_affect) { ssao_direct_light_affect = p_direct_light_affect; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } float Environment::get_ssao_direct_light_affect() const { @@ -458,25 +382,16 @@ float Environment::get_ssao_direct_light_affect() const { void Environment::set_ssao_ao_channel_affect(float p_ao_channel_affect) { ssao_ao_channel_affect = p_ao_channel_affect; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } float Environment::get_ssao_ao_channel_affect() const { return ssao_ao_channel_affect; } -void Environment::set_ao_color(const Color &p_color) { - ao_color = p_color; - RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); -} - -Color Environment::get_ao_color() const { - return ao_color; -} - void Environment::set_ssao_blur(SSAOBlur p_blur) { ssao_blur = p_blur; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } Environment::SSAOBlur Environment::get_ssao_blur() const { @@ -485,16 +400,175 @@ Environment::SSAOBlur Environment::get_ssao_blur() const { void Environment::set_ssao_edge_sharpness(float p_edge_sharpness) { ssao_edge_sharpness = p_edge_sharpness; - RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + _update_ssao(); } float Environment::get_ssao_edge_sharpness() const { return ssao_edge_sharpness; } +void Environment::_update_ssao() { + RS::get_singleton()->environment_set_ssao( + environment, + ssao_enabled, + ssao_radius, + ssao_intensity, + ssao_bias, + ssao_direct_light_affect, + ssao_ao_channel_affect, + RS::EnvironmentSSAOBlur(ssao_blur), + ssao_edge_sharpness); +} + +// SDFGI + +void Environment::set_sdfgi_enabled(bool p_enabled) { + sdfgi_enabled = p_enabled; + _update_sdfgi(); +} + +bool Environment::is_sdfgi_enabled() const { + return sdfgi_enabled; +} + +void Environment::set_sdfgi_cascades(SDFGICascades p_cascades) { + sdfgi_cascades = p_cascades; + _update_sdfgi(); +} + +Environment::SDFGICascades Environment::get_sdfgi_cascades() const { + return sdfgi_cascades; +} + +void Environment::set_sdfgi_min_cell_size(float p_size) { + sdfgi_min_cell_size = p_size; + _change_notify("sdfgi_max_distance"); + _change_notify("sdfgi_cascade0_distance"); + _update_sdfgi(); +} + +float Environment::get_sdfgi_min_cell_size() const { + return sdfgi_min_cell_size; +} + +void Environment::set_sdfgi_max_distance(float p_distance) { + p_distance /= 64.0; + int cc[3] = { 4, 6, 8 }; + int cascades = cc[sdfgi_cascades]; + for (int i = 0; i < cascades; i++) { + p_distance *= 0.5; //halve for each cascade + } + sdfgi_min_cell_size = p_distance; + _change_notify("sdfgi_min_cell_size"); + _change_notify("sdfgi_cascade0_distance"); + _update_sdfgi(); +} + +float Environment::get_sdfgi_max_distance() const { + float md = sdfgi_min_cell_size; + md *= 64.0; + int cc[3] = { 4, 6, 8 }; + int cascades = cc[sdfgi_cascades]; + for (int i = 0; i < cascades; i++) { + md *= 2.0; + } + return md; +} + +void Environment::set_sdfgi_cascade0_distance(float p_distance) { + sdfgi_min_cell_size = p_distance / 64.0; + _change_notify("sdfgi_min_cell_size"); + _change_notify("sdfgi_max_distance"); + _update_sdfgi(); +} + +float Environment::get_sdfgi_cascade0_distance() const { + return sdfgi_min_cell_size * 64.0; +} + +void Environment::set_sdfgi_y_scale(SDFGIYScale p_y_scale) { + sdfgi_y_scale = p_y_scale; + _update_sdfgi(); +} + +Environment::SDFGIYScale Environment::get_sdfgi_y_scale() const { + return sdfgi_y_scale; +} + +void Environment::set_sdfgi_use_occlusion(bool p_enabled) { + sdfgi_use_occlusion = p_enabled; + _update_sdfgi(); +} + +bool Environment::is_sdfgi_using_occlusion() const { + return sdfgi_use_occlusion; +} + +void Environment::set_sdfgi_use_multi_bounce(bool p_enabled) { + sdfgi_use_multibounce = p_enabled; + _update_sdfgi(); +} + +bool Environment::is_sdfgi_using_multi_bounce() const { + return sdfgi_use_multibounce; +} + +void Environment::set_sdfgi_read_sky_light(bool p_enabled) { + sdfgi_read_sky_light = p_enabled; + _update_sdfgi(); +} + +bool Environment::is_sdfgi_reading_sky_light() const { + return sdfgi_read_sky_light; +} + +void Environment::set_sdfgi_energy(float p_energy) { + sdfgi_energy = p_energy; + _update_sdfgi(); +} + +float Environment::get_sdfgi_energy() const { + return sdfgi_energy; +} + +void Environment::set_sdfgi_normal_bias(float p_bias) { + sdfgi_normal_bias = p_bias; + _update_sdfgi(); +} + +float Environment::get_sdfgi_normal_bias() const { + return sdfgi_normal_bias; +} + +void Environment::set_sdfgi_probe_bias(float p_bias) { + sdfgi_probe_bias = p_bias; + _update_sdfgi(); +} + +float Environment::get_sdfgi_probe_bias() const { + return sdfgi_probe_bias; +} + +void Environment::_update_sdfgi() { + RS::get_singleton()->environment_set_sdfgi( + environment, + sdfgi_enabled, + RS::EnvironmentSDFGICascades(sdfgi_cascades), + sdfgi_min_cell_size, + RS::EnvironmentSDFGIYScale(sdfgi_y_scale), + sdfgi_use_occlusion, + sdfgi_use_multibounce, + sdfgi_read_sky_light, + sdfgi_energy, + sdfgi_normal_bias, + sdfgi_probe_bias); +} + +// Glow + void Environment::set_glow_enabled(bool p_enabled) { glow_enabled = p_enabled; - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); _change_notify(); } @@ -502,7 +576,7 @@ bool Environment::is_glow_enabled() const { return glow_enabled; } -void Environment::set_glow_level(int p_level, bool p_enabled) { +void Environment::set_glow_level_enabled(int p_level, bool p_enabled) { ERR_FAIL_INDEX(p_level, RS::MAX_GLOW_LEVELS); if (p_enabled) { @@ -511,7 +585,7 @@ void Environment::set_glow_level(int p_level, bool p_enabled) { glow_levels &= ~(1 << p_level); } - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); } bool Environment::is_glow_level_enabled(int p_level) const { @@ -522,8 +596,7 @@ bool Environment::is_glow_level_enabled(int p_level) const { void Environment::set_glow_intensity(float p_intensity) { glow_intensity = p_intensity; - - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); } float Environment::get_glow_intensity() const { @@ -532,7 +605,7 @@ float Environment::get_glow_intensity() const { void Environment::set_glow_strength(float p_strength) { glow_strength = p_strength; - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); } float Environment::get_glow_strength() const { @@ -541,7 +614,7 @@ float Environment::get_glow_strength() const { void Environment::set_glow_mix(float p_mix) { glow_mix = p_mix; - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); } float Environment::get_glow_mix() const { @@ -550,8 +623,7 @@ float Environment::get_glow_mix() const { void Environment::set_glow_bloom(float p_threshold) { glow_bloom = p_threshold; - - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); } float Environment::get_glow_bloom() const { @@ -560,8 +632,7 @@ float Environment::get_glow_bloom() const { void Environment::set_glow_blend_mode(GlowBlendMode p_mode) { glow_blend_mode = p_mode; - - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); _change_notify(); } @@ -571,37 +642,51 @@ Environment::GlowBlendMode Environment::get_glow_blend_mode() const { void Environment::set_glow_hdr_bleed_threshold(float p_threshold) { glow_hdr_bleed_threshold = p_threshold; - - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); } float Environment::get_glow_hdr_bleed_threshold() const { return glow_hdr_bleed_threshold; } +void Environment::set_glow_hdr_bleed_scale(float p_scale) { + glow_hdr_bleed_scale = p_scale; + _update_glow(); +} + +float Environment::get_glow_hdr_bleed_scale() const { + return glow_hdr_bleed_scale; +} + void Environment::set_glow_hdr_luminance_cap(float p_amount) { glow_hdr_luminance_cap = p_amount; - - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); + _update_glow(); } float Environment::get_glow_hdr_luminance_cap() const { return glow_hdr_luminance_cap; } -void Environment::set_glow_hdr_bleed_scale(float p_scale) { - glow_hdr_bleed_scale = p_scale; - - RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap); +void Environment::_update_glow() { + RS::get_singleton()->environment_set_glow( + environment, + glow_enabled, + glow_levels, + glow_intensity, + glow_strength, + glow_mix, + glow_bloom, + RS::EnvironmentGlowBlendMode(glow_blend_mode), + glow_hdr_bleed_threshold, + glow_hdr_bleed_scale, + glow_hdr_luminance_cap); } -float Environment::get_glow_hdr_bleed_scale() const { - return glow_hdr_bleed_scale; -} +// Fog void Environment::set_fog_enabled(bool p_enabled) { fog_enabled = p_enabled; - RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + _update_fog(); _change_notify(); } @@ -611,7 +696,7 @@ bool Environment::is_fog_enabled() const { void Environment::set_fog_color(const Color &p_color) { fog_color = p_color; - RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + _update_fog(); } Color Environment::get_fog_color() const { @@ -620,7 +705,7 @@ Color Environment::get_fog_color() const { void Environment::set_fog_sun_color(const Color &p_color) { fog_sun_color = p_color; - RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + _update_fog(); } Color Environment::get_fog_sun_color() const { @@ -629,16 +714,25 @@ Color Environment::get_fog_sun_color() const { void Environment::set_fog_sun_amount(float p_amount) { fog_sun_amount = p_amount; - RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + _update_fog(); } float Environment::get_fog_sun_amount() const { return fog_sun_amount; } +void Environment::_update_fog() { + RS::get_singleton()->environment_set_fog( + environment, + fog_enabled, + fog_color, + fog_sun_color, + fog_sun_amount); +} + void Environment::set_fog_depth_enabled(bool p_enabled) { fog_depth_enabled = p_enabled; - RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + _update_fog_depth(); } bool Environment::is_fog_depth_enabled() const { @@ -647,7 +741,7 @@ bool Environment::is_fog_depth_enabled() const { void Environment::set_fog_depth_begin(float p_distance) { fog_depth_begin = p_distance; - RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + _update_fog_depth(); } float Environment::get_fog_depth_begin() const { @@ -656,7 +750,7 @@ float Environment::get_fog_depth_begin() const { void Environment::set_fog_depth_end(float p_distance) { fog_depth_end = p_distance; - RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + _update_fog_depth(); } float Environment::get_fog_depth_end() const { @@ -665,7 +759,7 @@ float Environment::get_fog_depth_end() const { void Environment::set_fog_depth_curve(float p_curve) { fog_depth_curve = p_curve; - RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + _update_fog_depth(); } float Environment::get_fog_depth_curve() const { @@ -674,7 +768,7 @@ float Environment::get_fog_depth_curve() const { void Environment::set_fog_transmit_enabled(bool p_enabled) { fog_transmit_enabled = p_enabled; - RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + _update_fog_depth(); } bool Environment::is_fog_transmit_enabled() const { @@ -683,16 +777,27 @@ bool Environment::is_fog_transmit_enabled() const { void Environment::set_fog_transmit_curve(float p_curve) { fog_transmit_curve = p_curve; - RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + _update_fog_depth(); } float Environment::get_fog_transmit_curve() const { return fog_transmit_curve; } +void Environment::_update_fog_depth() { + RS::get_singleton()->environment_set_fog_depth( + environment, + fog_depth_enabled, + fog_depth_begin, + fog_depth_end, + fog_depth_curve, + fog_transmit_enabled, + fog_transmit_curve); +} + void Environment::set_fog_height_enabled(bool p_enabled) { fog_height_enabled = p_enabled; - RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + _update_fog_height(); } bool Environment::is_fog_height_enabled() const { @@ -701,7 +806,7 @@ bool Environment::is_fog_height_enabled() const { void Environment::set_fog_height_min(float p_distance) { fog_height_min = p_distance; - RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + _update_fog_height(); } float Environment::get_fog_height_min() const { @@ -710,7 +815,7 @@ float Environment::get_fog_height_min() const { void Environment::set_fog_height_max(float p_distance) { fog_height_max = p_distance; - RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + _update_fog_height(); } float Environment::get_fog_height_max() const { @@ -719,13 +824,163 @@ float Environment::get_fog_height_max() const { void Environment::set_fog_height_curve(float p_distance) { fog_height_curve = p_distance; - RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + _update_fog_height(); } float Environment::get_fog_height_curve() const { return fog_height_curve; } +void Environment::_update_fog_height() { + RS::get_singleton()->environment_set_fog_height( + environment, + fog_height_enabled, + fog_height_min, + fog_height_max, + fog_height_curve); +} + +// Adjustment + +void Environment::set_adjustment_enabled(bool p_enabled) { + adjustment_enabled = p_enabled; + _update_adjustment(); + _change_notify(); +} + +bool Environment::is_adjustment_enabled() const { + return adjustment_enabled; +} + +void Environment::set_adjustment_brightness(float p_brightness) { + adjustment_brightness = p_brightness; + _update_adjustment(); +} + +float Environment::get_adjustment_brightness() const { + return adjustment_brightness; +} + +void Environment::set_adjustment_contrast(float p_contrast) { + adjustment_contrast = p_contrast; + _update_adjustment(); +} + +float Environment::get_adjustment_contrast() const { + return adjustment_contrast; +} + +void Environment::set_adjustment_saturation(float p_saturation) { + adjustment_saturation = p_saturation; + _update_adjustment(); +} + +float Environment::get_adjustment_saturation() const { + return adjustment_saturation; +} + +void Environment::set_adjustment_color_correction(const Ref<Texture2D> &p_ramp) { + adjustment_color_correction = p_ramp; + _update_adjustment(); +} + +Ref<Texture2D> Environment::get_adjustment_color_correction() const { + return adjustment_color_correction; +} + +void Environment::_update_adjustment() { + RS::get_singleton()->environment_set_adjustment( + environment, + adjustment_enabled, + adjustment_brightness, + adjustment_contrast, + adjustment_saturation, + adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); +} + +// Private methods, constructor and destructor + +void Environment::_validate_property(PropertyInfo &property) const { + if (property.name == "sky" || property.name == "sky_custom_fov" || property.name == "sky_rotation" || property.name == "ambient_light/sky_contribution") { + if (bg_mode != BG_SKY && ambient_source != AMBIENT_SOURCE_SKY && reflection_source != REFLECTION_SOURCE_SKY) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } + + if (property.name == "glow_intensity" && glow_blend_mode == GLOW_BLEND_MODE_MIX) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + + if (property.name == "glow_mix" && glow_blend_mode != GLOW_BLEND_MODE_MIX) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + + if (property.name == "background_color") { + if (bg_mode != BG_COLOR && ambient_source != AMBIENT_SOURCE_COLOR) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } + + if (property.name == "background_canvas_max_layer") { + if (bg_mode != BG_CANVAS) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + } + } + + if (property.name == "background_camera_feed_id") { + if (bg_mode != BG_CAMERA_FEED) { + property.usage = PROPERTY_USAGE_NOEDITOR; + } + } + + static const char *hide_prefixes[] = { + "fog_", + "auto_exposure_", + "ss_reflections_", + "ssao_", + "glow_", + "adjustment_", + nullptr + + }; + + static const char *high_end_prefixes[] = { + "auto_exposure_", + "tonemap_", + "ss_reflections_", + "ssao_", + nullptr + + }; + + const char **prefixes = hide_prefixes; + while (*prefixes) { + String prefix = String(*prefixes); + + String enabled = prefix + "enabled"; + if (property.name.begins_with(prefix) && property.name != enabled && !bool(get(enabled))) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + return; + } + + prefixes++; + } + + if (RenderingServer::get_singleton()->is_low_end()) { + prefixes = high_end_prefixes; + while (*prefixes) { + String prefix = String(*prefixes); + + if (property.name.begins_with(prefix)) { + property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; + return; + } + + prefixes++; + } + } +} + #ifndef DISABLE_DEPRECATED // Kept for compatibility from 3.x to 4.0. bool Environment::_set(const StringName &p_name, const Variant &p_value) { @@ -746,160 +1001,102 @@ bool Environment::_set(const StringName &p_name, const Variant &p_value) { #endif void Environment::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background); - ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky); - ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov); - ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation); - ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color); - ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy); - ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer); - ClassDB::bind_method(D_METHOD("set_ambient_light_color", "color"), &Environment::set_ambient_light_color); - ClassDB::bind_method(D_METHOD("set_ambient_light_energy", "energy"), &Environment::set_ambient_light_energy); - ClassDB::bind_method(D_METHOD("set_ambient_light_sky_contribution", "energy"), &Environment::set_ambient_light_sky_contribution); - ClassDB::bind_method(D_METHOD("set_camera_feed_id", "camera_feed_id"), &Environment::set_camera_feed_id); - ClassDB::bind_method(D_METHOD("set_ambient_source", "source"), &Environment::set_ambient_source); - ClassDB::bind_method(D_METHOD("set_reflection_source", "source"), &Environment::set_reflection_source); + // Background + ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background); ClassDB::bind_method(D_METHOD("get_background"), &Environment::get_background); + ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky); ClassDB::bind_method(D_METHOD("get_sky"), &Environment::get_sky); + ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov); ClassDB::bind_method(D_METHOD("get_sky_custom_fov"), &Environment::get_sky_custom_fov); + ClassDB::bind_method(D_METHOD("set_sky_rotation", "euler_radians"), &Environment::set_sky_rotation); ClassDB::bind_method(D_METHOD("get_sky_rotation"), &Environment::get_sky_rotation); + ClassDB::bind_method(D_METHOD("set_bg_color", "color"), &Environment::set_bg_color); ClassDB::bind_method(D_METHOD("get_bg_color"), &Environment::get_bg_color); + ClassDB::bind_method(D_METHOD("set_bg_energy", "energy"), &Environment::set_bg_energy); ClassDB::bind_method(D_METHOD("get_bg_energy"), &Environment::get_bg_energy); + ClassDB::bind_method(D_METHOD("set_canvas_max_layer", "layer"), &Environment::set_canvas_max_layer); ClassDB::bind_method(D_METHOD("get_canvas_max_layer"), &Environment::get_canvas_max_layer); - ClassDB::bind_method(D_METHOD("get_ambient_light_color"), &Environment::get_ambient_light_color); - ClassDB::bind_method(D_METHOD("get_ambient_light_energy"), &Environment::get_ambient_light_energy); - ClassDB::bind_method(D_METHOD("get_ambient_light_sky_contribution"), &Environment::get_ambient_light_sky_contribution); + ClassDB::bind_method(D_METHOD("set_camera_feed_id", "id"), &Environment::set_camera_feed_id); ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &Environment::get_camera_feed_id); - ClassDB::bind_method(D_METHOD("get_ambient_source"), &Environment::get_ambient_source); - ClassDB::bind_method(D_METHOD("get_reflection_source"), &Environment::get_reflection_source); - ClassDB::bind_method(D_METHOD("set_ao_color", "color"), &Environment::set_ao_color); - ClassDB::bind_method(D_METHOD("get_ao_color"), &Environment::get_ao_color); ADD_GROUP("Background", "background_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Canvas,Keep,Camera Feed"), "set_background", "get_background"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "background_canvas_max_layer", PROPERTY_HINT_RANGE, "-1000,1000,1"), "set_canvas_max_layer", "get_canvas_max_layer"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "background_color"), "set_bg_color", "get_bg_color"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "background_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bg_energy", "get_bg_energy"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "background_canvas_max_layer", PROPERTY_HINT_RANGE, "-1000,1000,1"), "set_canvas_max_layer", "get_canvas_max_layer"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "background_camera_feed_id", PROPERTY_HINT_RANGE, "1,10,1"), "set_camera_feed_id", "get_camera_feed_id"); + ADD_GROUP("Sky", "sky_"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "sky_rotation"), "set_sky_rotation", "get_sky_rotation"); + + // Ambient light + + ClassDB::bind_method(D_METHOD("set_ambient_light_color", "color"), &Environment::set_ambient_light_color); + ClassDB::bind_method(D_METHOD("get_ambient_light_color"), &Environment::get_ambient_light_color); + ClassDB::bind_method(D_METHOD("set_ambient_source", "source"), &Environment::set_ambient_source); + ClassDB::bind_method(D_METHOD("get_ambient_source"), &Environment::get_ambient_source); + ClassDB::bind_method(D_METHOD("set_ambient_light_energy", "energy"), &Environment::set_ambient_light_energy); + ClassDB::bind_method(D_METHOD("get_ambient_light_energy"), &Environment::get_ambient_light_energy); + ClassDB::bind_method(D_METHOD("set_ambient_light_sky_contribution", "ratio"), &Environment::set_ambient_light_sky_contribution); + ClassDB::bind_method(D_METHOD("get_ambient_light_sky_contribution"), &Environment::get_ambient_light_sky_contribution); + ClassDB::bind_method(D_METHOD("set_reflection_source", "source"), &Environment::set_reflection_source); + ClassDB::bind_method(D_METHOD("get_reflection_source"), &Environment::get_reflection_source); + ClassDB::bind_method(D_METHOD("set_ao_color", "color"), &Environment::set_ao_color); + ClassDB::bind_method(D_METHOD("get_ao_color"), &Environment::get_ao_color); + ADD_GROUP("Ambient Light", "ambient_light_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "ambient_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Color,Sky"), "set_ambient_source", "get_ambient_source"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_color"), "set_ambient_light_color", "get_ambient_light_color"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_light_sky_contribution", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ambient_light_sky_contribution", "get_ambient_light_sky_contribution"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ambient_light_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_ambient_light_energy", "get_ambient_light_energy"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ambient_light_occlusion_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ao_color", "get_ao_color"); + ADD_GROUP("Reflected Light", "reflected_light_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "reflected_light_source", PROPERTY_HINT_ENUM, "Background,Disabled,Sky"), "set_reflection_source", "get_reflection_source"); - ClassDB::bind_method(D_METHOD("set_fog_enabled", "enabled"), &Environment::set_fog_enabled); - ClassDB::bind_method(D_METHOD("is_fog_enabled"), &Environment::is_fog_enabled); - - ClassDB::bind_method(D_METHOD("set_fog_color", "color"), &Environment::set_fog_color); - ClassDB::bind_method(D_METHOD("get_fog_color"), &Environment::get_fog_color); - - ClassDB::bind_method(D_METHOD("set_fog_sun_color", "color"), &Environment::set_fog_sun_color); - ClassDB::bind_method(D_METHOD("get_fog_sun_color"), &Environment::get_fog_sun_color); - - ClassDB::bind_method(D_METHOD("set_fog_sun_amount", "amount"), &Environment::set_fog_sun_amount); - ClassDB::bind_method(D_METHOD("get_fog_sun_amount"), &Environment::get_fog_sun_amount); - - ClassDB::bind_method(D_METHOD("set_fog_depth_enabled", "enabled"), &Environment::set_fog_depth_enabled); - ClassDB::bind_method(D_METHOD("is_fog_depth_enabled"), &Environment::is_fog_depth_enabled); - - ClassDB::bind_method(D_METHOD("set_fog_depth_begin", "distance"), &Environment::set_fog_depth_begin); - ClassDB::bind_method(D_METHOD("get_fog_depth_begin"), &Environment::get_fog_depth_begin); - - ClassDB::bind_method(D_METHOD("set_fog_depth_end", "distance"), &Environment::set_fog_depth_end); - ClassDB::bind_method(D_METHOD("get_fog_depth_end"), &Environment::get_fog_depth_end); - - ClassDB::bind_method(D_METHOD("set_fog_depth_curve", "curve"), &Environment::set_fog_depth_curve); - ClassDB::bind_method(D_METHOD("get_fog_depth_curve"), &Environment::get_fog_depth_curve); - - ClassDB::bind_method(D_METHOD("set_fog_transmit_enabled", "enabled"), &Environment::set_fog_transmit_enabled); - ClassDB::bind_method(D_METHOD("is_fog_transmit_enabled"), &Environment::is_fog_transmit_enabled); - - ClassDB::bind_method(D_METHOD("set_fog_transmit_curve", "curve"), &Environment::set_fog_transmit_curve); - ClassDB::bind_method(D_METHOD("get_fog_transmit_curve"), &Environment::get_fog_transmit_curve); - - ClassDB::bind_method(D_METHOD("set_fog_height_enabled", "enabled"), &Environment::set_fog_height_enabled); - ClassDB::bind_method(D_METHOD("is_fog_height_enabled"), &Environment::is_fog_height_enabled); - - ClassDB::bind_method(D_METHOD("set_fog_height_min", "height"), &Environment::set_fog_height_min); - ClassDB::bind_method(D_METHOD("get_fog_height_min"), &Environment::get_fog_height_min); - - ClassDB::bind_method(D_METHOD("set_fog_height_max", "height"), &Environment::set_fog_height_max); - ClassDB::bind_method(D_METHOD("get_fog_height_max"), &Environment::get_fog_height_max); - - ClassDB::bind_method(D_METHOD("set_fog_height_curve", "curve"), &Environment::set_fog_height_curve); - ClassDB::bind_method(D_METHOD("get_fog_height_curve"), &Environment::get_fog_height_curve); - - ADD_GROUP("Fog", "fog_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_color"), "set_fog_color", "get_fog_color"); - ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_sun_color"), "set_fog_sun_color", "get_fog_sun_color"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_sun_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fog_sun_amount", "get_fog_sun_amount"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_depth_enabled"), "set_fog_depth_enabled", "is_fog_depth_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_begin", PROPERTY_HINT_RANGE, "0,4000,0.1"), "set_fog_depth_begin", "get_fog_depth_begin"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_end", PROPERTY_HINT_RANGE, "0,4000,0.1,or_greater"), "set_fog_depth_end", "get_fog_depth_end"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_curve", PROPERTY_HINT_EXP_EASING), "set_fog_depth_curve", "get_fog_depth_curve"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_transmit_enabled"), "set_fog_transmit_enabled", "is_fog_transmit_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_transmit_curve", PROPERTY_HINT_EXP_EASING), "set_fog_transmit_curve", "get_fog_transmit_curve"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_height_enabled"), "set_fog_height_enabled", "is_fog_height_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_min", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_min", "get_fog_height_min"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_max", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_max", "get_fog_height_max"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_curve", PROPERTY_HINT_EXP_EASING), "set_fog_height_curve", "get_fog_height_curve"); + // Tonemap ClassDB::bind_method(D_METHOD("set_tonemapper", "mode"), &Environment::set_tonemapper); ClassDB::bind_method(D_METHOD("get_tonemapper"), &Environment::get_tonemapper); - ClassDB::bind_method(D_METHOD("set_tonemap_exposure", "exposure"), &Environment::set_tonemap_exposure); ClassDB::bind_method(D_METHOD("get_tonemap_exposure"), &Environment::get_tonemap_exposure); - ClassDB::bind_method(D_METHOD("set_tonemap_white", "white"), &Environment::set_tonemap_white); ClassDB::bind_method(D_METHOD("get_tonemap_white"), &Environment::get_tonemap_white); - - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure", "auto_exposure"), &Environment::set_tonemap_auto_exposure); - ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure"), &Environment::get_tonemap_auto_exposure); - + ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_enabled", "enabled"), &Environment::set_tonemap_auto_exposure_enabled); + ClassDB::bind_method(D_METHOD("is_tonemap_auto_exposure_enabled"), &Environment::is_tonemap_auto_exposure_enabled); ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_max", "exposure_max"), &Environment::set_tonemap_auto_exposure_max); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_max"), &Environment::get_tonemap_auto_exposure_max); - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_min", "exposure_min"), &Environment::set_tonemap_auto_exposure_min); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_min"), &Environment::get_tonemap_auto_exposure_min); - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_speed", "exposure_speed"), &Environment::set_tonemap_auto_exposure_speed); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_speed"), &Environment::get_tonemap_auto_exposure_speed); - ClassDB::bind_method(D_METHOD("set_tonemap_auto_exposure_grey", "exposure_grey"), &Environment::set_tonemap_auto_exposure_grey); ClassDB::bind_method(D_METHOD("get_tonemap_auto_exposure_grey"), &Environment::get_tonemap_auto_exposure_grey); ADD_GROUP("Tonemap", "tonemap_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,Aces"), "set_tonemapper", "get_tonemapper"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tonemap_mode", PROPERTY_HINT_ENUM, "Linear,Reinhard,Filmic,ACES"), "set_tonemapper", "get_tonemapper"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_exposure", "get_tonemap_exposure"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tonemap_white", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_white", "get_tonemap_white"); ADD_GROUP("Auto Exposure", "auto_exposure_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_tonemap_auto_exposure", "get_tonemap_auto_exposure"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_exposure_enabled"), "set_tonemap_auto_exposure_enabled", "is_tonemap_auto_exposure_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_scale", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_grey", "get_tonemap_auto_exposure_grey"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_min_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_min", "get_tonemap_auto_exposure_min"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_max_luma", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_tonemap_auto_exposure_max", "get_tonemap_auto_exposure_max"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "auto_exposure_speed", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_tonemap_auto_exposure_speed", "get_tonemap_auto_exposure_speed"); + // SSR + ClassDB::bind_method(D_METHOD("set_ssr_enabled", "enabled"), &Environment::set_ssr_enabled); ClassDB::bind_method(D_METHOD("is_ssr_enabled"), &Environment::is_ssr_enabled); - ClassDB::bind_method(D_METHOD("set_ssr_max_steps", "max_steps"), &Environment::set_ssr_max_steps); ClassDB::bind_method(D_METHOD("get_ssr_max_steps"), &Environment::get_ssr_max_steps); - ClassDB::bind_method(D_METHOD("set_ssr_fade_in", "fade_in"), &Environment::set_ssr_fade_in); ClassDB::bind_method(D_METHOD("get_ssr_fade_in"), &Environment::get_ssr_fade_in); - ClassDB::bind_method(D_METHOD("set_ssr_fade_out", "fade_out"), &Environment::set_ssr_fade_out); ClassDB::bind_method(D_METHOD("get_ssr_fade_out"), &Environment::get_ssr_fade_out); - ClassDB::bind_method(D_METHOD("set_ssr_depth_tolerance", "depth_tolerance"), &Environment::set_ssr_depth_tolerance); ClassDB::bind_method(D_METHOD("get_ssr_depth_tolerance"), &Environment::get_ssr_depth_tolerance); @@ -910,27 +1107,22 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ss_reflections_fade_out", PROPERTY_HINT_EXP_EASING), "set_ssr_fade_out", "get_ssr_fade_out"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ss_reflections_depth_tolerance", PROPERTY_HINT_RANGE, "0.01,128,0.1"), "set_ssr_depth_tolerance", "get_ssr_depth_tolerance"); + // SSAO + ClassDB::bind_method(D_METHOD("set_ssao_enabled", "enabled"), &Environment::set_ssao_enabled); ClassDB::bind_method(D_METHOD("is_ssao_enabled"), &Environment::is_ssao_enabled); - ClassDB::bind_method(D_METHOD("set_ssao_radius", "radius"), &Environment::set_ssao_radius); ClassDB::bind_method(D_METHOD("get_ssao_radius"), &Environment::get_ssao_radius); - ClassDB::bind_method(D_METHOD("set_ssao_intensity", "intensity"), &Environment::set_ssao_intensity); ClassDB::bind_method(D_METHOD("get_ssao_intensity"), &Environment::get_ssao_intensity); - ClassDB::bind_method(D_METHOD("set_ssao_bias", "bias"), &Environment::set_ssao_bias); ClassDB::bind_method(D_METHOD("get_ssao_bias"), &Environment::get_ssao_bias); - ClassDB::bind_method(D_METHOD("set_ssao_direct_light_affect", "amount"), &Environment::set_ssao_direct_light_affect); ClassDB::bind_method(D_METHOD("get_ssao_direct_light_affect"), &Environment::get_ssao_direct_light_affect); - ClassDB::bind_method(D_METHOD("set_ssao_ao_channel_affect", "amount"), &Environment::set_ssao_ao_channel_affect); ClassDB::bind_method(D_METHOD("get_ssao_ao_channel_affect"), &Environment::get_ssao_ao_channel_affect); - ClassDB::bind_method(D_METHOD("set_ssao_blur", "mode"), &Environment::set_ssao_blur); ClassDB::bind_method(D_METHOD("get_ssao_blur"), &Environment::get_ssao_blur); - ClassDB::bind_method(D_METHOD("set_ssao_edge_sharpness", "edge_sharpness"), &Environment::set_ssao_edge_sharpness); ClassDB::bind_method(D_METHOD("get_ssao_edge_sharpness"), &Environment::get_ssao_edge_sharpness); @@ -944,77 +1136,161 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "ssao_blur", PROPERTY_HINT_ENUM, "Disabled,1x1,2x2,3x3"), "set_ssao_blur", "get_ssao_blur"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ssao_edge_sharpness", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_ssao_edge_sharpness", "get_ssao_edge_sharpness"); + // SDFGI + + ClassDB::bind_method(D_METHOD("set_sdfgi_enabled", "enabled"), &Environment::set_sdfgi_enabled); + ClassDB::bind_method(D_METHOD("is_sdfgi_enabled"), &Environment::is_sdfgi_enabled); + ClassDB::bind_method(D_METHOD("set_sdfgi_cascades", "amount"), &Environment::set_sdfgi_cascades); + ClassDB::bind_method(D_METHOD("get_sdfgi_cascades"), &Environment::get_sdfgi_cascades); + ClassDB::bind_method(D_METHOD("set_sdfgi_min_cell_size", "size"), &Environment::set_sdfgi_min_cell_size); + ClassDB::bind_method(D_METHOD("get_sdfgi_min_cell_size"), &Environment::get_sdfgi_min_cell_size); + ClassDB::bind_method(D_METHOD("set_sdfgi_max_distance", "distance"), &Environment::set_sdfgi_max_distance); + ClassDB::bind_method(D_METHOD("get_sdfgi_max_distance"), &Environment::get_sdfgi_max_distance); + ClassDB::bind_method(D_METHOD("set_sdfgi_cascade0_distance", "distance"), &Environment::set_sdfgi_cascade0_distance); + ClassDB::bind_method(D_METHOD("get_sdfgi_cascade0_distance"), &Environment::get_sdfgi_cascade0_distance); + ClassDB::bind_method(D_METHOD("set_sdfgi_y_scale", "scale"), &Environment::set_sdfgi_y_scale); + ClassDB::bind_method(D_METHOD("get_sdfgi_y_scale"), &Environment::get_sdfgi_y_scale); + ClassDB::bind_method(D_METHOD("set_sdfgi_use_occlusion", "enable"), &Environment::set_sdfgi_use_occlusion); + ClassDB::bind_method(D_METHOD("is_sdfgi_using_occlusion"), &Environment::is_sdfgi_using_occlusion); + ClassDB::bind_method(D_METHOD("set_sdfgi_use_multi_bounce", "enable"), &Environment::set_sdfgi_use_multi_bounce); + ClassDB::bind_method(D_METHOD("is_sdfgi_using_multi_bounce"), &Environment::is_sdfgi_using_multi_bounce); + ClassDB::bind_method(D_METHOD("set_sdfgi_read_sky_light", "enable"), &Environment::set_sdfgi_read_sky_light); + ClassDB::bind_method(D_METHOD("is_sdfgi_reading_sky_light"), &Environment::is_sdfgi_reading_sky_light); + ClassDB::bind_method(D_METHOD("set_sdfgi_energy", "amount"), &Environment::set_sdfgi_energy); + ClassDB::bind_method(D_METHOD("get_sdfgi_energy"), &Environment::get_sdfgi_energy); + ClassDB::bind_method(D_METHOD("set_sdfgi_normal_bias", "bias"), &Environment::set_sdfgi_normal_bias); + ClassDB::bind_method(D_METHOD("get_sdfgi_normal_bias"), &Environment::get_sdfgi_normal_bias); + ClassDB::bind_method(D_METHOD("set_sdfgi_probe_bias", "bias"), &Environment::set_sdfgi_probe_bias); + ClassDB::bind_method(D_METHOD("get_sdfgi_probe_bias"), &Environment::get_sdfgi_probe_bias); + + ADD_GROUP("SDFGI", "sdfgi_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_enabled"), "set_sdfgi_enabled", "is_sdfgi_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_multi_bounce"), "set_sdfgi_use_multi_bounce", "is_sdfgi_using_multi_bounce"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_use_occlusion"), "set_sdfgi_use_occlusion", "is_sdfgi_using_occlusion"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sdfgi_read_sky_light"), "set_sdfgi_read_sky_light", "is_sdfgi_reading_sky_light"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_cascades", PROPERTY_HINT_ENUM, "4 Cascades,6 Cascades,8 Cascades"), "set_sdfgi_cascades", "get_sdfgi_cascades"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_min_cell_size", PROPERTY_HINT_RANGE, "0.01,64,0.01"), "set_sdfgi_min_cell_size", "get_sdfgi_min_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_cascade0_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_cascade0_distance", "get_sdfgi_cascade0_distance"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_max_distance", PROPERTY_HINT_RANGE, "0.1,16384,0.1,or_greater"), "set_sdfgi_max_distance", "get_sdfgi_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sdfgi_y_scale", PROPERTY_HINT_ENUM, "Disable,75%,50%"), "set_sdfgi_y_scale", "get_sdfgi_y_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_energy"), "set_sdfgi_energy", "get_sdfgi_energy"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_normal_bias"), "set_sdfgi_normal_bias", "get_sdfgi_normal_bias"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sdfgi_probe_bias"), "set_sdfgi_probe_bias", "get_sdfgi_probe_bias"); + + // Glow + ClassDB::bind_method(D_METHOD("set_glow_enabled", "enabled"), &Environment::set_glow_enabled); ClassDB::bind_method(D_METHOD("is_glow_enabled"), &Environment::is_glow_enabled); - - ClassDB::bind_method(D_METHOD("set_glow_level", "idx", "enabled"), &Environment::set_glow_level); + ClassDB::bind_method(D_METHOD("set_glow_level_enabled", "idx", "enabled"), &Environment::set_glow_level_enabled); ClassDB::bind_method(D_METHOD("is_glow_level_enabled", "idx"), &Environment::is_glow_level_enabled); - ClassDB::bind_method(D_METHOD("set_glow_intensity", "intensity"), &Environment::set_glow_intensity); ClassDB::bind_method(D_METHOD("get_glow_intensity"), &Environment::get_glow_intensity); - ClassDB::bind_method(D_METHOD("set_glow_strength", "strength"), &Environment::set_glow_strength); ClassDB::bind_method(D_METHOD("get_glow_strength"), &Environment::get_glow_strength); - ClassDB::bind_method(D_METHOD("set_glow_mix", "mix"), &Environment::set_glow_mix); ClassDB::bind_method(D_METHOD("get_glow_mix"), &Environment::get_glow_mix); - ClassDB::bind_method(D_METHOD("set_glow_bloom", "amount"), &Environment::set_glow_bloom); ClassDB::bind_method(D_METHOD("get_glow_bloom"), &Environment::get_glow_bloom); - ClassDB::bind_method(D_METHOD("set_glow_blend_mode", "mode"), &Environment::set_glow_blend_mode); ClassDB::bind_method(D_METHOD("get_glow_blend_mode"), &Environment::get_glow_blend_mode); - ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_threshold", "threshold"), &Environment::set_glow_hdr_bleed_threshold); ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_threshold"), &Environment::get_glow_hdr_bleed_threshold); - - ClassDB::bind_method(D_METHOD("set_glow_hdr_luminance_cap", "amount"), &Environment::set_glow_hdr_luminance_cap); - ClassDB::bind_method(D_METHOD("get_glow_hdr_luminance_cap"), &Environment::get_glow_hdr_luminance_cap); - ClassDB::bind_method(D_METHOD("set_glow_hdr_bleed_scale", "scale"), &Environment::set_glow_hdr_bleed_scale); ClassDB::bind_method(D_METHOD("get_glow_hdr_bleed_scale"), &Environment::get_glow_hdr_bleed_scale); + ClassDB::bind_method(D_METHOD("set_glow_hdr_luminance_cap", "amount"), &Environment::set_glow_hdr_luminance_cap); + ClassDB::bind_method(D_METHOD("get_glow_hdr_luminance_cap"), &Environment::get_glow_hdr_luminance_cap); ADD_GROUP("Glow", "glow_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "glow_enabled"), "set_glow_enabled", "is_glow_enabled"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/1"), "set_glow_level", "is_glow_level_enabled", 0); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/2"), "set_glow_level", "is_glow_level_enabled", 1); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/3"), "set_glow_level", "is_glow_level_enabled", 2); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/4"), "set_glow_level", "is_glow_level_enabled", 3); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/5"), "set_glow_level", "is_glow_level_enabled", 4); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/6"), "set_glow_level", "is_glow_level_enabled", 5); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level", "is_glow_level_enabled", 6); - + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/1"), "set_glow_level_enabled", "is_glow_level_enabled", 0); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/2"), "set_glow_level_enabled", "is_glow_level_enabled", 1); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/3"), "set_glow_level_enabled", "is_glow_level_enabled", 2); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/4"), "set_glow_level_enabled", "is_glow_level_enabled", 3); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/5"), "set_glow_level_enabled", "is_glow_level_enabled", 4); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/6"), "set_glow_level_enabled", "is_glow_level_enabled", 5); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "glow_levels/7"), "set_glow_level_enabled", "is_glow_level_enabled", 6); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_intensity", PROPERTY_HINT_RANGE, "0.0,8.0,0.01"), "set_glow_intensity", "get_glow_intensity"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_strength", PROPERTY_HINT_RANGE, "0.0,2.0,0.01"), "set_glow_strength", "get_glow_strength"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_mix", PROPERTY_HINT_RANGE, "0.0,1.0,0.001"), "set_glow_mix", "get_glow_mix"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_bloom", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_glow_bloom", "get_glow_bloom"); ADD_PROPERTY(PropertyInfo(Variant::INT, "glow_blend_mode", PROPERTY_HINT_ENUM, "Additive,Screen,Softlight,Replace,Mix"), "set_glow_blend_mode", "get_glow_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_threshold", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_threshold", "get_glow_hdr_bleed_threshold"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_scale", PROPERTY_HINT_RANGE, "0.0,4.0,0.01"), "set_glow_hdr_bleed_scale", "get_glow_hdr_bleed_scale"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "glow_hdr_luminance_cap", PROPERTY_HINT_RANGE, "0.0,256.0,0.01"), "set_glow_hdr_luminance_cap", "get_glow_hdr_luminance_cap"); - ClassDB::bind_method(D_METHOD("set_adjustment_enable", "enabled"), &Environment::set_adjustment_enable); - ClassDB::bind_method(D_METHOD("is_adjustment_enabled"), &Environment::is_adjustment_enabled); + // Fog + + ClassDB::bind_method(D_METHOD("set_fog_enabled", "enabled"), &Environment::set_fog_enabled); + ClassDB::bind_method(D_METHOD("is_fog_enabled"), &Environment::is_fog_enabled); + ClassDB::bind_method(D_METHOD("set_fog_color", "color"), &Environment::set_fog_color); + ClassDB::bind_method(D_METHOD("get_fog_color"), &Environment::get_fog_color); + ClassDB::bind_method(D_METHOD("set_fog_sun_color", "color"), &Environment::set_fog_sun_color); + ClassDB::bind_method(D_METHOD("get_fog_sun_color"), &Environment::get_fog_sun_color); + ClassDB::bind_method(D_METHOD("set_fog_sun_amount", "amount"), &Environment::set_fog_sun_amount); + ClassDB::bind_method(D_METHOD("get_fog_sun_amount"), &Environment::get_fog_sun_amount); + + ClassDB::bind_method(D_METHOD("set_fog_depth_enabled", "enabled"), &Environment::set_fog_depth_enabled); + ClassDB::bind_method(D_METHOD("is_fog_depth_enabled"), &Environment::is_fog_depth_enabled); + ClassDB::bind_method(D_METHOD("set_fog_depth_begin", "distance"), &Environment::set_fog_depth_begin); + ClassDB::bind_method(D_METHOD("get_fog_depth_begin"), &Environment::get_fog_depth_begin); + ClassDB::bind_method(D_METHOD("set_fog_depth_end", "distance"), &Environment::set_fog_depth_end); + ClassDB::bind_method(D_METHOD("get_fog_depth_end"), &Environment::get_fog_depth_end); + ClassDB::bind_method(D_METHOD("set_fog_depth_curve", "curve"), &Environment::set_fog_depth_curve); + ClassDB::bind_method(D_METHOD("get_fog_depth_curve"), &Environment::get_fog_depth_curve); + ClassDB::bind_method(D_METHOD("set_fog_transmit_enabled", "enabled"), &Environment::set_fog_transmit_enabled); + ClassDB::bind_method(D_METHOD("is_fog_transmit_enabled"), &Environment::is_fog_transmit_enabled); + ClassDB::bind_method(D_METHOD("set_fog_transmit_curve", "curve"), &Environment::set_fog_transmit_curve); + ClassDB::bind_method(D_METHOD("get_fog_transmit_curve"), &Environment::get_fog_transmit_curve); + + ClassDB::bind_method(D_METHOD("set_fog_height_enabled", "enabled"), &Environment::set_fog_height_enabled); + ClassDB::bind_method(D_METHOD("is_fog_height_enabled"), &Environment::is_fog_height_enabled); + ClassDB::bind_method(D_METHOD("set_fog_height_min", "height"), &Environment::set_fog_height_min); + ClassDB::bind_method(D_METHOD("get_fog_height_min"), &Environment::get_fog_height_min); + ClassDB::bind_method(D_METHOD("set_fog_height_max", "height"), &Environment::set_fog_height_max); + ClassDB::bind_method(D_METHOD("get_fog_height_max"), &Environment::get_fog_height_max); + ClassDB::bind_method(D_METHOD("set_fog_height_curve", "curve"), &Environment::set_fog_height_curve); + ClassDB::bind_method(D_METHOD("get_fog_height_curve"), &Environment::get_fog_height_curve); + + ADD_GROUP("Fog", "fog_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_enabled"), "set_fog_enabled", "is_fog_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_color"), "set_fog_color", "get_fog_color"); + ADD_PROPERTY(PropertyInfo(Variant::COLOR, "fog_sun_color"), "set_fog_sun_color", "get_fog_sun_color"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_sun_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_fog_sun_amount", "get_fog_sun_amount"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_depth_enabled"), "set_fog_depth_enabled", "is_fog_depth_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_begin", PROPERTY_HINT_RANGE, "0,4000,0.1"), "set_fog_depth_begin", "get_fog_depth_begin"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_end", PROPERTY_HINT_RANGE, "0,4000,0.1,or_greater"), "set_fog_depth_end", "get_fog_depth_end"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_depth_curve", PROPERTY_HINT_EXP_EASING), "set_fog_depth_curve", "get_fog_depth_curve"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_transmit_enabled"), "set_fog_transmit_enabled", "is_fog_transmit_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_transmit_curve", PROPERTY_HINT_EXP_EASING), "set_fog_transmit_curve", "get_fog_transmit_curve"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "fog_height_enabled"), "set_fog_height_enabled", "is_fog_height_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_min", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_min", "get_fog_height_min"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_max", PROPERTY_HINT_RANGE, "-4000,4000,0.1,or_lesser,or_greater"), "set_fog_height_max", "get_fog_height_max"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_height_curve", PROPERTY_HINT_EXP_EASING), "set_fog_height_curve", "get_fog_height_curve"); + + // Adjustment + ClassDB::bind_method(D_METHOD("set_adjustment_enabled", "enabled"), &Environment::set_adjustment_enabled); + ClassDB::bind_method(D_METHOD("is_adjustment_enabled"), &Environment::is_adjustment_enabled); ClassDB::bind_method(D_METHOD("set_adjustment_brightness", "brightness"), &Environment::set_adjustment_brightness); ClassDB::bind_method(D_METHOD("get_adjustment_brightness"), &Environment::get_adjustment_brightness); - ClassDB::bind_method(D_METHOD("set_adjustment_contrast", "contrast"), &Environment::set_adjustment_contrast); ClassDB::bind_method(D_METHOD("get_adjustment_contrast"), &Environment::get_adjustment_contrast); - ClassDB::bind_method(D_METHOD("set_adjustment_saturation", "saturation"), &Environment::set_adjustment_saturation); ClassDB::bind_method(D_METHOD("get_adjustment_saturation"), &Environment::get_adjustment_saturation); - ClassDB::bind_method(D_METHOD("set_adjustment_color_correction", "color_correction"), &Environment::set_adjustment_color_correction); ClassDB::bind_method(D_METHOD("get_adjustment_color_correction"), &Environment::get_adjustment_color_correction); ADD_GROUP("Adjustments", "adjustment_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "adjustment_enabled"), "set_adjustment_enable", "is_adjustment_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "adjustment_enabled"), "set_adjustment_enabled", "is_adjustment_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_brightness", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_brightness", "get_adjustment_brightness"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_contrast", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_contrast", "get_adjustment_contrast"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "adjustment_saturation", PROPERTY_HINT_RANGE, "0.01,8,0.01"), "set_adjustment_saturation", "get_adjustment_saturation"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "adjustment_color_correction", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_adjustment_color_correction", "get_adjustment_color_correction"); + // Constants + BIND_ENUM_CONSTANT(BG_CLEAR_COLOR); BIND_ENUM_CONSTANT(BG_COLOR); BIND_ENUM_CONSTANT(BG_SKY); @@ -1032,254 +1308,49 @@ void Environment::_bind_methods() { BIND_ENUM_CONSTANT(REFLECTION_SOURCE_DISABLED); BIND_ENUM_CONSTANT(REFLECTION_SOURCE_SKY); + BIND_ENUM_CONSTANT(TONE_MAPPER_LINEAR); + BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARDT); + BIND_ENUM_CONSTANT(TONE_MAPPER_FILMIC); + BIND_ENUM_CONSTANT(TONE_MAPPER_ACES); + BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_ADDITIVE); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SCREEN); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_REPLACE); BIND_ENUM_CONSTANT(GLOW_BLEND_MODE_MIX); - BIND_ENUM_CONSTANT(TONE_MAPPER_LINEAR); - BIND_ENUM_CONSTANT(TONE_MAPPER_REINHARDT); - BIND_ENUM_CONSTANT(TONE_MAPPER_FILMIC); - BIND_ENUM_CONSTANT(TONE_MAPPER_ACES); - BIND_ENUM_CONSTANT(SSAO_BLUR_DISABLED); BIND_ENUM_CONSTANT(SSAO_BLUR_1x1); BIND_ENUM_CONSTANT(SSAO_BLUR_2x2); BIND_ENUM_CONSTANT(SSAO_BLUR_3x3); -} - -Environment::Environment() { - environment = RS::get_singleton()->environment_create(); - - bg_mode = BG_CLEAR_COLOR; - bg_sky_custom_fov = 0; - bg_energy = 1.0; - bg_canvas_max_layer = 0; - ambient_energy = 1.0; - //ambient_sky_contribution = 1.0; - ambient_source = AMBIENT_SOURCE_BG; - reflection_source = REFLECTION_SOURCE_BG; - set_ambient_light_sky_contribution(1.0); - set_camera_feed_id(1); - - tone_mapper = TONE_MAPPER_LINEAR; - tonemap_exposure = 1.0; - tonemap_white = 1.0; - tonemap_auto_exposure = false; - tonemap_auto_exposure_max = 8; - tonemap_auto_exposure_min = 0.05; - tonemap_auto_exposure_speed = 0.5; - tonemap_auto_exposure_grey = 0.4; - - set_tonemapper(tone_mapper); //update - - adjustment_enabled = false; - adjustment_contrast = 1.0; - adjustment_saturation = 1.0; - adjustment_brightness = 1.0; - - set_adjustment_enable(adjustment_enabled); //update - - ssr_enabled = false; - ssr_max_steps = 64; - ssr_fade_in = 0.15; - ssr_fade_out = 2.0; - ssr_depth_tolerance = 0.2; - - ssao_enabled = false; - ssao_radius = 1; - ssao_intensity = 1; - ssao_bias = 0.01; - ssao_direct_light_affect = 0.0; - ssao_ao_channel_affect = 0.0; - ssao_blur = SSAO_BLUR_3x3; - set_ssao_edge_sharpness(4); - - glow_enabled = false; - glow_levels = (1 << 2) | (1 << 4); - glow_intensity = 0.8; - glow_strength = 1.0; - glow_mix = 0.05; - glow_bloom = 0.0; - glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT; - glow_hdr_bleed_threshold = 1.0; - glow_hdr_luminance_cap = 12.0; - glow_hdr_bleed_scale = 2.0; - - fog_enabled = false; - fog_color = Color(0.5, 0.5, 0.5); - fog_sun_color = Color(0.8, 0.8, 0.0); - fog_sun_amount = 0; - - fog_depth_enabled = true; - - fog_depth_begin = 10; - fog_depth_end = 100; - fog_depth_curve = 1; - - fog_transmit_enabled = false; - fog_transmit_curve = 1; - - fog_height_enabled = false; - fog_height_min = 10; - fog_height_max = 0; - fog_height_curve = 1; - - set_fog_color(Color(0.5, 0.6, 0.7)); - set_fog_sun_color(Color(1.0, 0.9, 0.7)); -} - -Environment::~Environment() { - RS::get_singleton()->free(environment); -} - -////////////////////// -void CameraEffects::set_dof_blur_far_enabled(bool p_enable) { - dof_blur_far_enabled = p_enable; - RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); -} - -bool CameraEffects::is_dof_blur_far_enabled() const { - return dof_blur_far_enabled; -} + BIND_ENUM_CONSTANT(SDFGI_CASCADES_4); + BIND_ENUM_CONSTANT(SDFGI_CASCADES_6); + BIND_ENUM_CONSTANT(SDFGI_CASCADES_8); -void CameraEffects::set_dof_blur_far_distance(float p_distance) { - dof_blur_far_distance = p_distance; - RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_DISABLED); + BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_75_PERCENT); + BIND_ENUM_CONSTANT(SDFGI_Y_SCALE_50_PERCENT); } -float CameraEffects::get_dof_blur_far_distance() const { - return dof_blur_far_distance; -} +Environment::Environment() { + environment = RS::get_singleton()->environment_create(); -void CameraEffects::set_dof_blur_far_transition(float p_distance) { - dof_blur_far_transition = p_distance; - RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); -} + set_camera_feed_id(bg_camera_feed_id); + _update_ambient_light(); + _update_tonemap(); + _update_ssr(); + _update_ssao(); + _update_sdfgi(); + _update_glow(); + _update_fog(); + _update_fog_depth(); + _update_fog_height(); + _update_adjustment(); -float CameraEffects::get_dof_blur_far_transition() const { - return dof_blur_far_transition; -} - -void CameraEffects::set_dof_blur_near_enabled(bool p_enable) { - dof_blur_near_enabled = p_enable; - RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); _change_notify(); } -bool CameraEffects::is_dof_blur_near_enabled() const { - return dof_blur_near_enabled; -} - -void CameraEffects::set_dof_blur_near_distance(float p_distance) { - dof_blur_near_distance = p_distance; - RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); -} - -float CameraEffects::get_dof_blur_near_distance() const { - return dof_blur_near_distance; -} - -void CameraEffects::set_dof_blur_near_transition(float p_distance) { - dof_blur_near_transition = p_distance; - RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); -} - -float CameraEffects::get_dof_blur_near_transition() const { - return dof_blur_near_transition; -} - -void CameraEffects::set_dof_blur_amount(float p_amount) { - dof_blur_amount = p_amount; - RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); -} - -float CameraEffects::get_dof_blur_amount() const { - return dof_blur_amount; -} - -void CameraEffects::set_override_exposure_enabled(bool p_enabled) { - override_exposure_enabled = p_enabled; - RS::get_singleton()->camera_effects_set_custom_exposure(camera_effects, override_exposure_enabled, override_exposure); -} - -bool CameraEffects::is_override_exposure_enabled() const { - return override_exposure_enabled; -} - -void CameraEffects::set_override_exposure(float p_exposure) { - override_exposure = p_exposure; - RS::get_singleton()->camera_effects_set_custom_exposure(camera_effects, override_exposure_enabled, override_exposure); -} - -float CameraEffects::get_override_exposure() const { - return override_exposure; -} - -RID CameraEffects::get_rid() const { - return camera_effects; -} - -void CameraEffects::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_dof_blur_far_enabled", "enabled"), &CameraEffects::set_dof_blur_far_enabled); - ClassDB::bind_method(D_METHOD("is_dof_blur_far_enabled"), &CameraEffects::is_dof_blur_far_enabled); - - ClassDB::bind_method(D_METHOD("set_dof_blur_far_distance", "intensity"), &CameraEffects::set_dof_blur_far_distance); - ClassDB::bind_method(D_METHOD("get_dof_blur_far_distance"), &CameraEffects::get_dof_blur_far_distance); - - ClassDB::bind_method(D_METHOD("set_dof_blur_far_transition", "intensity"), &CameraEffects::set_dof_blur_far_transition); - ClassDB::bind_method(D_METHOD("get_dof_blur_far_transition"), &CameraEffects::get_dof_blur_far_transition); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_enabled", "enabled"), &CameraEffects::set_dof_blur_near_enabled); - ClassDB::bind_method(D_METHOD("is_dof_blur_near_enabled"), &CameraEffects::is_dof_blur_near_enabled); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_distance", "intensity"), &CameraEffects::set_dof_blur_near_distance); - ClassDB::bind_method(D_METHOD("get_dof_blur_near_distance"), &CameraEffects::get_dof_blur_near_distance); - - ClassDB::bind_method(D_METHOD("set_dof_blur_near_transition", "intensity"), &CameraEffects::set_dof_blur_near_transition); - ClassDB::bind_method(D_METHOD("get_dof_blur_near_transition"), &CameraEffects::get_dof_blur_near_transition); - - ClassDB::bind_method(D_METHOD("set_dof_blur_amount", "intensity"), &CameraEffects::set_dof_blur_amount); - ClassDB::bind_method(D_METHOD("get_dof_blur_amount"), &CameraEffects::get_dof_blur_amount); - - ClassDB::bind_method(D_METHOD("set_override_exposure_enabled", "enable"), &CameraEffects::set_override_exposure_enabled); - ClassDB::bind_method(D_METHOD("is_override_exposure_enabled"), &CameraEffects::is_override_exposure_enabled); - - ClassDB::bind_method(D_METHOD("set_override_exposure", "exposure"), &CameraEffects::set_override_exposure); - ClassDB::bind_method(D_METHOD("get_override_exposure"), &CameraEffects::get_override_exposure); - - ADD_GROUP("DOF Blur", "dof_blur_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_far_enabled"), "set_dof_blur_far_enabled", "is_dof_blur_far_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_distance", "get_dof_blur_far_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_far_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_far_transition", "get_dof_blur_far_transition"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dof_blur_near_enabled"), "set_dof_blur_near_enabled", "is_dof_blur_near_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_distance", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_distance", "get_dof_blur_near_distance"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_near_transition", PROPERTY_HINT_EXP_RANGE, "0.01,8192,0.01"), "set_dof_blur_near_transition", "get_dof_blur_near_transition"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dof_blur_amount", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dof_blur_amount", "get_dof_blur_amount"); - ADD_GROUP("Override Exposure", "override_"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "override_exposure_enable"), "set_override_exposure_enabled", "is_override_exposure_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "override_exposure", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_override_exposure", "get_override_exposure"); -} - -CameraEffects::CameraEffects() { - camera_effects = RS::get_singleton()->camera_effects_create(); - - dof_blur_far_enabled = false; - dof_blur_far_distance = 10; - dof_blur_far_transition = 5; - - dof_blur_near_enabled = false; - dof_blur_near_distance = 2; - dof_blur_near_transition = 1; - - set_dof_blur_amount(0.1); - - override_exposure_enabled = false; - set_override_exposure(1.0); -} - -CameraEffects::~CameraEffects() { - RS::get_singleton()->free(camera_effects); +Environment::~Environment() { + RS::get_singleton()->free(environment); } diff --git a/scene/resources/environment.h b/scene/resources/environment.h index b8caa59aab..5dbeeb2fc8 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -41,7 +41,6 @@ class Environment : public Resource { public: enum BGMode { - BG_CLEAR_COLOR, BG_COLOR, BG_SKY, @@ -68,7 +67,26 @@ public: TONE_MAPPER_LINEAR, TONE_MAPPER_REINHARDT, TONE_MAPPER_FILMIC, - TONE_MAPPER_ACES + TONE_MAPPER_ACES, + }; + + enum SSAOBlur { + SSAO_BLUR_DISABLED, + SSAO_BLUR_1x1, + SSAO_BLUR_2x2, + SSAO_BLUR_3x3, + }; + + enum SDFGICascades { + SDFGI_CASCADES_4, + SDFGI_CASCADES_6, + SDFGI_CASCADES_8, + }; + + enum SDFGIYScale { + SDFGI_Y_SCALE_DISABLED, + SDFGI_Y_SCALE_75_PERCENT, + SDFGI_Y_SCALE_50_PERCENT, }; enum GlowBlendMode { @@ -79,89 +97,112 @@ public: GLOW_BLEND_MODE_MIX, }; - enum SSAOBlur { - SSAO_BLUR_DISABLED, - SSAO_BLUR_1x1, - SSAO_BLUR_2x2, - SSAO_BLUR_3x3 - }; - private: RID environment; + // Background BGMode bg_mode = BG_CLEAR_COLOR; Ref<Sky> bg_sky; - float bg_sky_custom_fov; - Vector3 sky_rotation; + float bg_sky_custom_fov = 0; + Vector3 bg_sky_rotation; Color bg_color; - float bg_energy; - int bg_canvas_max_layer; + float bg_energy = 1.0; + int bg_canvas_max_layer = 0; + int bg_camera_feed_id = 1; + + // Ambient light Color ambient_color; - float ambient_energy; + AmbientSource ambient_source = AMBIENT_SOURCE_BG; + float ambient_energy = 1.0; + float ambient_sky_contribution = 1.0; + ReflectionSource reflection_source = REFLECTION_SOURCE_BG; Color ao_color; - float ambient_sky_contribution; - int camera_feed_id; - AmbientSource ambient_source; - ReflectionSource reflection_source; + void _update_ambient_light(); + // Tonemap ToneMapper tone_mapper = TONE_MAPPER_LINEAR; - float tonemap_exposure; - float tonemap_white; - bool tonemap_auto_exposure; - float tonemap_auto_exposure_max; - float tonemap_auto_exposure_min; - float tonemap_auto_exposure_speed; - float tonemap_auto_exposure_grey; - - bool adjustment_enabled; - float adjustment_contrast; - float adjustment_saturation; - float adjustment_brightness; - Ref<Texture2D> adjustment_color_correction; - - bool ssr_enabled; - int ssr_max_steps; - float ssr_fade_in; - float ssr_fade_out; - float ssr_depth_tolerance; - - bool ssao_enabled; - float ssao_radius; - float ssao_intensity; - float ssao_bias; - float ssao_direct_light_affect; - float ssao_ao_channel_affect; + float tonemap_exposure = 1.0; + float tonemap_white = 1.0; + bool tonemap_auto_exposure_enabled = false; + float tonemap_auto_exposure_min = 0.05; + float tonemap_auto_exposure_max = 8; + float tonemap_auto_exposure_speed = 0.5; + float tonemap_auto_exposure_grey = 0.4; + void _update_tonemap(); + + // SSR + bool ssr_enabled = false; + int ssr_max_steps = 64; + float ssr_fade_in = 0.15; + float ssr_fade_out = 2.0; + float ssr_depth_tolerance = 0.2; + void _update_ssr(); + + // SSAO + bool ssao_enabled = false; + float ssao_radius = 1.0; + float ssao_intensity = 1.0; + float ssao_bias = 0.01; + float ssao_direct_light_affect = 0.0; + float ssao_ao_channel_affect = 0.0; SSAOBlur ssao_blur = SSAO_BLUR_3x3; - float ssao_edge_sharpness; - - bool glow_enabled; - int glow_levels; - float glow_intensity; - float glow_strength; - float glow_mix; - float glow_bloom; - GlowBlendMode glow_blend_mode = GLOW_BLEND_MODE_ADDITIVE; - float glow_hdr_bleed_threshold; - float glow_hdr_bleed_scale; - float glow_hdr_luminance_cap; - - bool fog_enabled; - Color fog_color; - Color fog_sun_color; - float fog_sun_amount; - - bool fog_depth_enabled; - float fog_depth_begin; - float fog_depth_end; - float fog_depth_curve; - - bool fog_transmit_enabled; - float fog_transmit_curve; - - bool fog_height_enabled; - float fog_height_min; - float fog_height_max; - float fog_height_curve; + float ssao_edge_sharpness = 4.0; + void _update_ssao(); + + // SDFGI + bool sdfgi_enabled = false; + SDFGICascades sdfgi_cascades = SDFGI_CASCADES_6; + float sdfgi_min_cell_size = 0.2; + SDFGIYScale sdfgi_y_scale = SDFGI_Y_SCALE_DISABLED; + bool sdfgi_use_occlusion = false; + bool sdfgi_use_multibounce = false; + bool sdfgi_read_sky_light = false; + float sdfgi_energy = 1.0; + float sdfgi_normal_bias = 1.1; + float sdfgi_probe_bias = 1.1; + void _update_sdfgi(); + + // Glow + bool glow_enabled = false; + int glow_levels = (1 << 2) | (1 << 4); + float glow_intensity = 0.8; + float glow_strength = 1.0; + float glow_mix = 0.05; + float glow_bloom = 0.0; + GlowBlendMode glow_blend_mode = GLOW_BLEND_MODE_SOFTLIGHT; + float glow_hdr_bleed_threshold = 1.0; + float glow_hdr_bleed_scale = 2.0; + float glow_hdr_luminance_cap = 12.0; + void _update_glow(); + + // Fog + bool fog_enabled = false; + Color fog_color = Color(0.5, 0.6, 0.7); + Color fog_sun_color = Color(1.0, 0.9, 0.7); + float fog_sun_amount = 0.0; + void _update_fog(); + + bool fog_depth_enabled = true; + float fog_depth_begin = 10.0; + float fog_depth_end = 100.0; + float fog_depth_curve = 1.0; + bool fog_transmit_enabled = false; + float fog_transmit_curve = 1.0; + void _update_fog_depth(); + + bool fog_height_enabled = false; + float fog_height_min = 10.0; + float fog_height_max = 0.0; + float fog_height_curve = 1.0; + void _update_fog_height(); + + // Adjustment + bool adjustment_enabled = false; + float adjustment_brightness = 1.0; + float adjustment_contrast = 1.0; + float adjustment_saturation = 1.0; + Ref<Texture2D> adjustment_color_correction; + void _update_adjustment(); protected: static void _bind_methods(); @@ -172,189 +213,179 @@ protected: #endif public: - void set_background(BGMode p_bg); + virtual RID get_rid() const; + // Background + void set_background(BGMode p_bg); + BGMode get_background() const; void set_sky(const Ref<Sky> &p_sky); + Ref<Sky> get_sky() const; void set_sky_custom_fov(float p_scale); + float get_sky_custom_fov() const; void set_sky_rotation(const Vector3 &p_rotation); + Vector3 get_sky_rotation() const; void set_bg_color(const Color &p_color); + Color get_bg_color() const; void set_bg_energy(float p_energy); + float get_bg_energy() const; void set_canvas_max_layer(int p_max_layer); + int get_canvas_max_layer() const; + void set_camera_feed_id(int p_id); + int get_camera_feed_id() const; + + // Ambient light void set_ambient_light_color(const Color &p_color); - void set_ambient_light_energy(float p_energy); - void set_ambient_light_sky_contribution(float p_energy); - void set_camera_feed_id(int p_camera_feed_id); + Color get_ambient_light_color() const; void set_ambient_source(AmbientSource p_source); AmbientSource get_ambient_source() const; - void set_reflection_source(ReflectionSource p_source); - ReflectionSource get_reflection_source() const; - - BGMode get_background() const; - Ref<Sky> get_sky() const; - float get_sky_custom_fov() const; - Vector3 get_sky_rotation() const; - Color get_bg_color() const; - float get_bg_energy() const; - int get_canvas_max_layer() const; - Color get_ambient_light_color() const; + void set_ambient_light_energy(float p_energy); float get_ambient_light_energy() const; + void set_ambient_light_sky_contribution(float p_ratio); float get_ambient_light_sky_contribution() const; - int get_camera_feed_id() const; + void set_reflection_source(ReflectionSource p_source); + ReflectionSource get_reflection_source() const; + void set_ao_color(const Color &p_color); + Color get_ao_color() const; + // Tonemap void set_tonemapper(ToneMapper p_tone_mapper); ToneMapper get_tonemapper() const; - void set_tonemap_exposure(float p_exposure); float get_tonemap_exposure() const; - void set_tonemap_white(float p_white); float get_tonemap_white() const; - - void set_tonemap_auto_exposure(bool p_enabled); - bool get_tonemap_auto_exposure() const; - - void set_tonemap_auto_exposure_max(float p_auto_exposure_max); - float get_tonemap_auto_exposure_max() const; - + void set_tonemap_auto_exposure_enabled(bool p_enabled); + bool is_tonemap_auto_exposure_enabled() const; void set_tonemap_auto_exposure_min(float p_auto_exposure_min); float get_tonemap_auto_exposure_min() const; - + void set_tonemap_auto_exposure_max(float p_auto_exposure_max); + float get_tonemap_auto_exposure_max() const; void set_tonemap_auto_exposure_speed(float p_auto_exposure_speed); float get_tonemap_auto_exposure_speed() const; - void set_tonemap_auto_exposure_grey(float p_auto_exposure_grey); float get_tonemap_auto_exposure_grey() const; - void set_adjustment_enable(bool p_enable); - bool is_adjustment_enabled() const; - - void set_adjustment_brightness(float p_brightness); - float get_adjustment_brightness() const; - - void set_adjustment_contrast(float p_contrast); - float get_adjustment_contrast() const; - - void set_adjustment_saturation(float p_saturation); - float get_adjustment_saturation() const; - - void set_adjustment_color_correction(const Ref<Texture2D> &p_ramp); - Ref<Texture2D> get_adjustment_color_correction() const; - - void set_ssr_enabled(bool p_enable); + // SSR + void set_ssr_enabled(bool p_enabled); bool is_ssr_enabled() const; - void set_ssr_max_steps(int p_steps); int get_ssr_max_steps() const; - void set_ssr_fade_in(float p_fade_in); float get_ssr_fade_in() const; - void set_ssr_fade_out(float p_fade_out); float get_ssr_fade_out() const; - void set_ssr_depth_tolerance(float p_depth_tolerance); float get_ssr_depth_tolerance() const; - void set_ssao_enabled(bool p_enable); + // SSAO + void set_ssao_enabled(bool p_enabled); bool is_ssao_enabled() const; - void set_ssao_radius(float p_radius); float get_ssao_radius() const; - void set_ssao_intensity(float p_intensity); float get_ssao_intensity() const; - void set_ssao_bias(float p_bias); float get_ssao_bias() const; - void set_ssao_direct_light_affect(float p_direct_light_affect); float get_ssao_direct_light_affect() const; - void set_ssao_ao_channel_affect(float p_ao_channel_affect); float get_ssao_ao_channel_affect() const; - - void set_ao_color(const Color &p_color); - Color get_ao_color() const; - void set_ssao_blur(SSAOBlur p_blur); SSAOBlur get_ssao_blur() const; - void set_ssao_edge_sharpness(float p_edge_sharpness); float get_ssao_edge_sharpness() const; + // SDFGI + void set_sdfgi_enabled(bool p_enabled); + bool is_sdfgi_enabled() const; + void set_sdfgi_cascades(SDFGICascades p_cascades); + SDFGICascades get_sdfgi_cascades() const; + void set_sdfgi_min_cell_size(float p_size); + float get_sdfgi_min_cell_size() const; + void set_sdfgi_max_distance(float p_distance); + float get_sdfgi_max_distance() const; + void set_sdfgi_cascade0_distance(float p_distance); + float get_sdfgi_cascade0_distance() const; + void set_sdfgi_y_scale(SDFGIYScale p_y_scale); + SDFGIYScale get_sdfgi_y_scale() const; + void set_sdfgi_use_occlusion(bool p_enabled); + bool is_sdfgi_using_occlusion() const; + void set_sdfgi_use_multi_bounce(bool p_enabled); + bool is_sdfgi_using_multi_bounce() const; + void set_sdfgi_read_sky_light(bool p_enabled); + bool is_sdfgi_reading_sky_light() const; + void set_sdfgi_energy(float p_energy); + float get_sdfgi_energy() const; + void set_sdfgi_normal_bias(float p_bias); + float get_sdfgi_normal_bias() const; + void set_sdfgi_probe_bias(float p_bias); + float get_sdfgi_probe_bias() const; + + // Glow void set_glow_enabled(bool p_enabled); bool is_glow_enabled() const; - - void set_glow_level(int p_level, bool p_enabled); + void set_glow_level_enabled(int p_level, bool p_enabled); bool is_glow_level_enabled(int p_level) const; - void set_glow_intensity(float p_intensity); float get_glow_intensity() const; - void set_glow_strength(float p_strength); float get_glow_strength() const; - void set_glow_mix(float p_mix); float get_glow_mix() const; - void set_glow_bloom(float p_threshold); float get_glow_bloom() const; - void set_glow_blend_mode(GlowBlendMode p_mode); GlowBlendMode get_glow_blend_mode() const; - void set_glow_hdr_bleed_threshold(float p_threshold); float get_glow_hdr_bleed_threshold() const; - - void set_glow_hdr_luminance_cap(float p_amount); - float get_glow_hdr_luminance_cap() const; - void set_glow_hdr_bleed_scale(float p_scale); float get_glow_hdr_bleed_scale() const; + void set_glow_hdr_luminance_cap(float p_amount); + float get_glow_hdr_luminance_cap() const; + // Fog void set_fog_enabled(bool p_enabled); bool is_fog_enabled() const; - void set_fog_color(const Color &p_color); Color get_fog_color() const; - void set_fog_sun_color(const Color &p_color); Color get_fog_sun_color() const; - void set_fog_sun_amount(float p_amount); float get_fog_sun_amount() const; void set_fog_depth_enabled(bool p_enabled); bool is_fog_depth_enabled() const; - void set_fog_depth_begin(float p_distance); float get_fog_depth_begin() const; - void set_fog_depth_end(float p_distance); float get_fog_depth_end() const; - void set_fog_depth_curve(float p_curve); float get_fog_depth_curve() const; - void set_fog_transmit_enabled(bool p_enabled); bool is_fog_transmit_enabled() const; - void set_fog_transmit_curve(float p_curve); float get_fog_transmit_curve() const; void set_fog_height_enabled(bool p_enabled); bool is_fog_height_enabled() const; - void set_fog_height_min(float p_distance); float get_fog_height_min() const; - void set_fog_height_max(float p_distance); float get_fog_height_max() const; - void set_fog_height_curve(float p_distance); float get_fog_height_curve() const; - virtual RID get_rid() const; + // Adjustment + void set_adjustment_enabled(bool p_enabled); + bool is_adjustment_enabled() const; + void set_adjustment_brightness(float p_brightness); + float get_adjustment_brightness() const; + void set_adjustment_contrast(float p_contrast); + float get_adjustment_contrast() const; + void set_adjustment_saturation(float p_saturation); + float get_adjustment_saturation() const; + void set_adjustment_color_correction(const Ref<Texture2D> &p_ramp); + Ref<Texture2D> get_adjustment_color_correction() const; Environment(); ~Environment(); @@ -364,63 +395,9 @@ VARIANT_ENUM_CAST(Environment::BGMode) VARIANT_ENUM_CAST(Environment::AmbientSource) VARIANT_ENUM_CAST(Environment::ReflectionSource) VARIANT_ENUM_CAST(Environment::ToneMapper) -VARIANT_ENUM_CAST(Environment::GlowBlendMode) VARIANT_ENUM_CAST(Environment::SSAOBlur) - -class CameraEffects : public Resource { - GDCLASS(CameraEffects, Resource); - -private: - RID camera_effects; - - bool dof_blur_far_enabled; - float dof_blur_far_distance; - float dof_blur_far_transition; - - bool dof_blur_near_enabled; - float dof_blur_near_distance; - float dof_blur_near_transition; - - float dof_blur_amount; - - bool override_exposure_enabled; - float override_exposure; - -protected: - static void _bind_methods(); - -public: - void set_dof_blur_far_enabled(bool p_enable); - bool is_dof_blur_far_enabled() const; - - void set_dof_blur_far_distance(float p_distance); - float get_dof_blur_far_distance() const; - - void set_dof_blur_far_transition(float p_distance); - float get_dof_blur_far_transition() const; - - void set_dof_blur_near_enabled(bool p_enable); - bool is_dof_blur_near_enabled() const; - - void set_dof_blur_near_distance(float p_distance); - float get_dof_blur_near_distance() const; - - void set_dof_blur_near_transition(float p_distance); - float get_dof_blur_near_transition() const; - - void set_dof_blur_amount(float p_amount); - float get_dof_blur_amount() const; - - void set_override_exposure_enabled(bool p_enabled); - bool is_override_exposure_enabled() const; - - void set_override_exposure(float p_exposure); - float get_override_exposure() const; - - virtual RID get_rid() const; - - CameraEffects(); - ~CameraEffects(); -}; +VARIANT_ENUM_CAST(Environment::SDFGICascades) +VARIANT_ENUM_CAST(Environment::SDFGIYScale) +VARIANT_ENUM_CAST(Environment::GlowBlendMode) #endif // ENVIRONMENT_H diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp index 54b6cde8bd..38d1346541 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -107,4 +107,4 @@ Sky::Sky() { Sky::~Sky() { RS::get_singleton()->free(sky); -}
\ No newline at end of file +} diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h index 81a27a7349..02a821637f 100644 --- a/scene/resources/world_3d.h +++ b/scene/resources/world_3d.h @@ -32,6 +32,7 @@ #define WORLD_3D_H #include "core/resource.h" +#include "scene/resources/camera_effects.h" #include "scene/resources/environment.h" #include "servers/physics_server_3d.h" #include "servers/rendering_server.h" diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 09d2914e05..6b70f41e57 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -184,6 +184,7 @@ void AudioDriverManager::initialize(int p_driver) { GLOBAL_DEF_RST("audio/enable_audio_input", false); GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); + GLOBAL_DEF_RST("audio/output_latency.web", 50); // Safer default output_latency for web. int failed_driver = -1; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 0ea11a2670..83e0a797a9 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -181,7 +181,7 @@ bool DisplayServer::screen_is_kept_on() const { return false; } -DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &) { +DisplayServer::WindowID DisplayServer::create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect) { ERR_FAIL_V_MSG(INVALID_WINDOW_ID, "Sub-windows not supported by this display server."); } @@ -402,7 +402,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list); ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position); - ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i())); + ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "flags", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i())); ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window); ClassDB::bind_method(D_METHOD("window_set_title", "title", "window_id"), &DisplayServer::window_set_title, DEFVAL(MAIN_WINDOW_ID)); diff --git a/servers/display_server.h b/servers/display_server.h index 166274f8ed..a4fcd29a4a 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -211,7 +211,7 @@ public: WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS) }; - virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i & = Rect2i()); + virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); virtual void delete_sub_window(WindowID p_id); virtual WindowID get_window_at_screen_position(const Point2i &p_position) const = 0; diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 2300c9cdee..8c7876e5cd 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -203,18 +203,18 @@ public: linear_velocity += p_impulse * _inv_mass; } - _FORCE_INLINE_ void apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse) { + _FORCE_INLINE_ void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) { linear_velocity += p_impulse * _inv_mass; - angular_velocity += _inv_inertia * p_offset.cross(p_impulse); + angular_velocity += _inv_inertia * p_position.cross(p_impulse); } _FORCE_INLINE_ void apply_torque_impulse(real_t p_torque) { angular_velocity += _inv_inertia * p_torque; } - _FORCE_INLINE_ void apply_bias_impulse(const Vector2 &p_pos, const Vector2 &p_j) { - biased_linear_velocity += p_j * _inv_mass; - biased_angular_velocity += _inv_inertia * p_pos.cross(p_j); + _FORCE_INLINE_ void apply_bias_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) { + biased_linear_velocity += p_impulse * _inv_mass; + biased_angular_velocity += _inv_inertia * p_position.cross(p_impulse); } void set_active(bool p_active); @@ -246,9 +246,9 @@ public: applied_force += p_force; } - _FORCE_INLINE_ void add_force(const Vector2 &p_offset, const Vector2 &p_force) { + _FORCE_INLINE_ void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) { applied_force += p_force; - applied_torque += p_offset.cross(p_force); + applied_torque += p_position.cross(p_force); } _FORCE_INLINE_ void add_torque(real_t p_torque) { @@ -360,10 +360,10 @@ public: virtual Transform2D get_transform() const { return body->get_transform(); } virtual void add_central_force(const Vector2 &p_force) { body->add_central_force(p_force); } - virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) { body->add_force(p_offset, p_force); } + virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) { body->add_force(p_force, p_position); } virtual void add_torque(real_t p_torque) { body->add_torque(p_torque); } virtual void apply_central_impulse(const Vector2 &p_impulse) { body->apply_central_impulse(p_impulse); } - virtual void apply_impulse(const Vector2 &p_offset, const Vector2 &p_force) { body->apply_impulse(p_offset, p_force); } + virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) { body->apply_impulse(p_impulse, p_position); } virtual void apply_torque_impulse(real_t p_torque) { body->apply_torque_impulse(p_torque); } virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); } diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index e483ddf1cc..5997959432 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -255,9 +255,8 @@ bool BodyPair2DSW::setup(real_t p_step) { if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_SHAPE) { motion_B = B->get_motion(); } - //faster to set than to check.. - //bool prev_collided=collided; + bool prev_collided = collided; collided = CollisionSolver2DSW::solve(shape_A_ptr, xform_A, motion_A, shape_B_ptr, xform_B, motion_B, _add_contact, this, &sep_axis); if (!collided) { @@ -285,8 +284,7 @@ bool BodyPair2DSW::setup(real_t p_step) { return false; } - //if (!prev_collided) { - { + if (!prev_collided) { if (A->is_shape_set_as_one_way_collision(shape_A)) { Vector2 direction = xform_A.get_axis(1).normalized(); bool valid = false; @@ -427,10 +425,9 @@ bool BodyPair2DSW::setup(real_t p_step) { // Apply normal + friction impulse Vector2 P = c.acc_normal_impulse * c.normal + c.acc_tangent_impulse * tangent; - A->apply_impulse(c.rA, -P); - B->apply_impulse(c.rB, P); + A->apply_impulse(-P, c.rA); + B->apply_impulse(P, c.rB); } - #endif c.bounce = combine_bounce(A, B); @@ -497,8 +494,8 @@ void BodyPair2DSW::solve(real_t p_step) { Vector2 j = c.normal * (c.acc_normal_impulse - jnOld) + tangent * (c.acc_tangent_impulse - jtOld); - A->apply_impulse(c.rA, -j); - B->apply_impulse(c.rB, j); + A->apply_impulse(-j, c.rA); + B->apply_impulse(j, c.rB); } } diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp index ae549ed2e4..ec74507e03 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp +++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "broad_phase_2d_hash_grid.h" +#include "collision_object_2d_sw.h" #include "core/project_settings.h" #define LARGE_ELEMENT_FI 1.01239812 @@ -70,20 +71,22 @@ void BroadPhase2DHashGrid::_unpair_attempt(Element *p_elem, Element *p_with) { void BroadPhase2DHashGrid::_check_motion(Element *p_elem) { for (Map<Element *, PairData *>::Element *E = p_elem->paired.front(); E; E = E->next()) { - bool pairing = p_elem->aabb.intersects(E->key()->aabb); - - if (pairing != E->get()->colliding) { - if (pairing) { - if (pair_callback) { - E->get()->ud = pair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, pair_userdata); - } - } else { - if (unpair_callback) { - unpair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, E->get()->ud, unpair_userdata); - } + 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) { + if (!E->get()->colliding || (logical_collision && !E->get()->ud && pair_callback)) { + E->get()->ud = pair_callback(p_elem->owner, p_elem->subindex, E->key()->owner, E->key()->subindex, pair_userdata); + } else if (E->get()->colliding && !logical_collision && E->get()->ud && 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 = pairing; + E->get()->colliding = true; + } else { // No physcial_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()->colliding = false; } } } @@ -317,23 +320,17 @@ void BroadPhase2DHashGrid::move(ID p_id, const Rect2 &p_aabb) { Element &e = E->get(); - if (p_aabb == e.aabb) { - return; - } - - if (p_aabb != Rect2()) { - _enter_grid(&e, p_aabb, e._static); - } - - if (e.aabb != Rect2()) { - _exit_grid(&e, e.aabb, e._static); + if (p_aabb != e.aabb) { + if (p_aabb != Rect2()) { + _enter_grid(&e, p_aabb, e._static); + } + if (e.aabb != Rect2()) { + _exit_grid(&e, e.aabb, e._static); + } + e.aabb = p_aabb; } - e.aabb = p_aabb; - _check_motion(&e); - - e.aabb = p_aabb; } void BroadPhase2DHashGrid::set_static(ID p_id, bool p_static) { diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 84a2baaa74..8caa53680d 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -168,10 +168,16 @@ public: return shapes[p_idx].one_way_collision_margin; } - void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; } + void set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; + _shape_changed(); + } _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } - void set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; } + void set_collision_layer(uint32_t p_layer) { + collision_layer = p_layer; + _shape_changed(); + } _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } void remove_shape(Shape2DSW *p_shape); diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp index 81e961e90d..e7d26645e9 100644 --- a/servers/physics_2d/joints_2d_sw.cpp +++ b/servers/physics_2d/joints_2d_sw.cpp @@ -136,9 +136,9 @@ bool PinJoint2DSW::setup(real_t p_step) { bias = delta * -(get_bias() == 0 ? space->get_constraint_bias() : get_bias()) * (1.0 / p_step); // apply accumulated impulse - A->apply_impulse(rA, -P); + A->apply_impulse(-P, rA); if (B) { - B->apply_impulse(rB, P); + B->apply_impulse(P, rB); } return true; @@ -161,9 +161,9 @@ void PinJoint2DSW::solve(real_t p_step) { Vector2 impulse = M.basis_xform(bias - rel_vel - Vector2(softness, softness) * P); - A->apply_impulse(rA, -impulse); + A->apply_impulse(-impulse, rA); if (B) { - B->apply_impulse(rB, impulse); + B->apply_impulse(impulse, rB); } P += impulse; @@ -301,8 +301,8 @@ bool GrooveJoint2DSW::setup(real_t p_step) { gbias = (delta * -(_b == 0 ? space->get_constraint_bias() : _b) * (1.0 / p_step)).clamped(get_max_bias()); // apply accumulated impulse - A->apply_impulse(rA, -jn_acc); - B->apply_impulse(rB, jn_acc); + A->apply_impulse(-jn_acc, rA); + B->apply_impulse(jn_acc, rB); correct = true; return true; @@ -320,8 +320,8 @@ void GrooveJoint2DSW::solve(real_t p_step) { j = jn_acc - jOld; - A->apply_impulse(rA, -j); - B->apply_impulse(rB, j); + A->apply_impulse(-j, rA); + B->apply_impulse(j, rB); } GrooveJoint2DSW::GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, Body2DSW *p_body_a, Body2DSW *p_body_b) : @@ -370,8 +370,8 @@ bool DampedSpringJoint2DSW::setup(real_t p_step) { real_t f_spring = (rest_length - dist) * stiffness; Vector2 j = n * f_spring * (p_step); - A->apply_impulse(rA, -j); - B->apply_impulse(rB, j); + A->apply_impulse(-j, rA); + B->apply_impulse(j, rB); return true; } @@ -386,8 +386,8 @@ void DampedSpringJoint2DSW::solve(real_t p_step) { target_vrn = vrn + v_damp; Vector2 j = n * v_damp * n_mass; - A->apply_impulse(rA, -j); - B->apply_impulse(rB, j); + A->apply_impulse(-j, rA); + B->apply_impulse(j, rB); } void DampedSpringJoint2DSW::set_param(PhysicsServer2D::DampedSpringParam p_param, real_t p_value) { diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 6983225668..1ed1ba6958 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -823,13 +823,13 @@ void PhysicsServer2DSW::body_apply_torque_impulse(RID p_body, real_t p_torque) { body->apply_torque_impulse(p_torque); } -void PhysicsServer2DSW::body_apply_impulse(RID p_body, const Vector2 &p_pos, const Vector2 &p_impulse) { +void PhysicsServer2DSW::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) { Body2DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); _update_shapes(); - body->apply_impulse(p_pos, p_impulse); + body->apply_impulse(p_impulse, p_position); body->wakeup(); }; @@ -841,11 +841,11 @@ void PhysicsServer2DSW::body_add_central_force(RID p_body, const Vector2 &p_forc body->wakeup(); }; -void PhysicsServer2DSW::body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force) { +void PhysicsServer2DSW::body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) { Body2DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->add_force(p_offset, p_force); + body->add_force(p_force, p_position); body->wakeup(); }; diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index 093c775cb5..9fcb7ff5f2 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -221,12 +221,12 @@ public: virtual real_t body_get_applied_torque(RID p_body) const; virtual void body_add_central_force(RID p_body, const Vector2 &p_force); - virtual void body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force); + virtual void body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()); virtual void body_add_torque(RID p_body, real_t p_torque); virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse); virtual void body_apply_torque_impulse(RID p_body, real_t p_torque); - virtual void body_apply_impulse(RID p_body, const Vector2 &p_pos, const Vector2 &p_impulse); + virtual void body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position = Vector2()); virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity); virtual void body_add_collision_exception(RID p_body, RID p_body_b); diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h index 483ea58620..2878c97c9d 100644 --- a/servers/physics_3d/body_3d_sw.h +++ b/servers/physics_3d/body_3d_sw.h @@ -216,23 +216,23 @@ public: _FORCE_INLINE_ const Vector3 &get_biased_linear_velocity() const { return biased_linear_velocity; } _FORCE_INLINE_ const Vector3 &get_biased_angular_velocity() const { return biased_angular_velocity; } - _FORCE_INLINE_ void apply_central_impulse(const Vector3 &p_j) { - linear_velocity += p_j * _inv_mass; + _FORCE_INLINE_ void apply_central_impulse(const Vector3 &p_impulse) { + linear_velocity += p_impulse * _inv_mass; } - _FORCE_INLINE_ void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { - linear_velocity += p_j * _inv_mass; - angular_velocity += _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); + _FORCE_INLINE_ void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) { + linear_velocity += p_impulse * _inv_mass; + angular_velocity += _inv_inertia_tensor.xform((p_position - center_of_mass).cross(p_impulse)); } - _FORCE_INLINE_ void apply_torque_impulse(const Vector3 &p_j) { - angular_velocity += _inv_inertia_tensor.xform(p_j); + _FORCE_INLINE_ void apply_torque_impulse(const Vector3 &p_impulse) { + angular_velocity += _inv_inertia_tensor.xform(p_impulse); } - _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_pos, const Vector3 &p_j, real_t p_max_delta_av = -1.0) { - biased_linear_velocity += p_j * _inv_mass; + _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3(), real_t p_max_delta_av = -1.0) { + biased_linear_velocity += p_impulse * _inv_mass; if (p_max_delta_av != 0.0) { - Vector3 delta_av = _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); + Vector3 delta_av = _inv_inertia_tensor.xform((p_position - center_of_mass).cross(p_impulse)); if (p_max_delta_av > 0 && delta_av.length() > p_max_delta_av) { delta_av = delta_av.normalized() * p_max_delta_av; } @@ -240,17 +240,17 @@ public: } } - _FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3 &p_j) { - biased_angular_velocity += _inv_inertia_tensor.xform(p_j); + _FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3 &p_impulse) { + biased_angular_velocity += _inv_inertia_tensor.xform(p_impulse); } _FORCE_INLINE_ void add_central_force(const Vector3 &p_force) { applied_force += p_force; } - _FORCE_INLINE_ void add_force(const Vector3 &p_force, const Vector3 &p_pos) { + _FORCE_INLINE_ void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) { applied_force += p_force; - applied_torque += (p_pos - center_of_mass).cross(p_force); + applied_torque += (p_position - center_of_mass).cross(p_force); } _FORCE_INLINE_ void add_torque(const Vector3 &p_torque) { @@ -403,11 +403,15 @@ public: virtual Transform get_transform() const { return body->get_transform(); } virtual void add_central_force(const Vector3 &p_force) { body->add_central_force(p_force); } - virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->add_force(p_force, p_pos); } + virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) { + body->add_force(p_force, p_position); + } virtual void add_torque(const Vector3 &p_torque) { body->add_torque(p_torque); } - virtual void apply_central_impulse(const Vector3 &p_j) { body->apply_central_impulse(p_j); } - virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { body->apply_impulse(p_pos, p_j); } - virtual void apply_torque_impulse(const Vector3 &p_j) { body->apply_torque_impulse(p_j); } + virtual void apply_central_impulse(const Vector3 &p_impulse) { body->apply_central_impulse(p_impulse); } + virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) { + body->apply_impulse(p_impulse, p_position); + } + virtual void apply_torque_impulse(const Vector3 &p_impulse) { body->apply_torque_impulse(p_impulse); } virtual void set_sleep_state(bool p_sleep) { body->set_active(!p_sleep); } virtual bool is_sleeping() const { return !body->is_active(); } diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp index a4f86badbe..848138940e 100644 --- a/servers/physics_3d/body_pair_3d_sw.cpp +++ b/servers/physics_3d/body_pair_3d_sw.cpp @@ -321,8 +321,8 @@ bool BodyPair3DSW::setup(real_t p_step) { c.depth = depth; Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse; - A->apply_impulse(c.rA + A->get_center_of_mass(), -j_vec); - B->apply_impulse(c.rB + B->get_center_of_mass(), j_vec); + A->apply_impulse(-j_vec, c.rA + A->get_center_of_mass()); + B->apply_impulse(j_vec, c.rB + B->get_center_of_mass()); c.acc_bias_impulse = 0; c.acc_bias_impulse_center_of_mass = 0; @@ -404,8 +404,8 @@ void BodyPair3DSW::solve(real_t p_step) { Vector3 j = c.normal * (c.acc_normal_impulse - jnOld); - A->apply_impulse(c.rA + A->get_center_of_mass(), -j); - B->apply_impulse(c.rB + B->get_center_of_mass(), j); + A->apply_impulse(-j, c.rA + A->get_center_of_mass()); + B->apply_impulse(j, c.rB + B->get_center_of_mass()); c.active = true; } @@ -447,8 +447,8 @@ void BodyPair3DSW::solve(real_t p_step) { jt = c.acc_tangent_impulse - jtOld; - A->apply_impulse(c.rA + A->get_center_of_mass(), -jt); - B->apply_impulse(c.rB + B->get_center_of_mass(), jt); + A->apply_impulse(-jt, c.rA + A->get_center_of_mass()); + B->apply_impulse(jt, c.rB + B->get_center_of_mass()); c.active = true; } diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h index 9506f14402..a3a5787ced 100644 --- a/servers/physics_3d/collision_object_3d_sw.h +++ b/servers/physics_3d/collision_object_3d_sw.h @@ -142,10 +142,16 @@ public: return shapes[p_idx].disabled; } - _FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; } + _FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) { + collision_layer = p_layer; + _shape_changed(); + } _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } - _FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; } + _FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) { + collision_mask = p_mask; + _shape_changed(); + } _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } _FORCE_INLINE_ bool test_collision_mask(CollisionObject3DSW *p_other) const { diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp index 9d10ede608..789d6687a4 100644 --- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp @@ -261,8 +261,8 @@ void ConeTwistJoint3DSW::solve(real_t p_timestep) { real_t impulse = depth * tau / p_timestep * jacDiagABInv - rel_vel * jacDiagABInv; m_appliedImpulse += impulse; Vector3 impulse_vector = normal * impulse; - A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); - B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); + A->apply_impulse(impulse_vector, pivotAInW - A->get_transform().origin); + B->apply_impulse(-impulse_vector, pivotBInW - B->get_transform().origin); } } diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp index 423bbc0dfd..fede40ca65 100644 --- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp @@ -205,8 +205,8 @@ real_t G6DOFTranslationalLimitMotor3DSW::solveLinearAxis( normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; Vector3 impulse_vector = axis_normal_on_a * normalImpulse; - body1->apply_impulse(rel_pos1, impulse_vector); - body2->apply_impulse(rel_pos2, -impulse_vector); + body1->apply_impulse(impulse_vector, rel_pos1); + body2->apply_impulse(-impulse_vector, rel_pos2); return normalImpulse; } diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp index a879b4ca7f..52c7389e1f 100644 --- a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp @@ -275,8 +275,8 @@ void HingeJoint3DSW::solve(real_t p_step) { real_t impulse = depth * tau / p_step * jacDiagABInv - rel_vel * jacDiagABInv; m_appliedImpulse += impulse; Vector3 impulse_vector = normal * impulse; - A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); - B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); + A->apply_impulse(impulse_vector, pivotAInW - A->get_transform().origin); + B->apply_impulse(-impulse_vector, pivotBInW - B->get_transform().origin); } } diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.cpp b/servers/physics_3d/joints/pin_joint_3d_sw.cpp index 230904408b..f028ad88f9 100644 --- a/servers/physics_3d/joints/pin_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/pin_joint_3d_sw.cpp @@ -119,8 +119,8 @@ void PinJoint3DSW::solve(real_t p_step) { m_appliedImpulse += impulse; Vector3 impulse_vector = normal * impulse; - A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); - B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); + A->apply_impulse(impulse_vector, pivotAInW - A->get_transform().origin); + B->apply_impulse(-impulse_vector, pivotBInW - B->get_transform().origin); normal[i] = 0; } diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/slider_joint_3d_sw.cpp index 5b4609f24e..43bd49b4b5 100644 --- a/servers/physics_3d/joints/slider_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/slider_joint_3d_sw.cpp @@ -197,8 +197,8 @@ void SliderJoint3DSW::solve(real_t p_step) { // calcutate and apply impulse real_t normalImpulse = softness * (restitution * depth / p_step - damping * rel_vel) * m_jacLinDiagABInv[i]; Vector3 impulse_vector = normal * normalImpulse; - A->apply_impulse(m_relPosA, impulse_vector); - B->apply_impulse(m_relPosB, -impulse_vector); + A->apply_impulse(impulse_vector, m_relPosA); + B->apply_impulse(-impulse_vector, m_relPosB); if (m_poweredLinMotor && (!i)) { // apply linear motor if (m_accumulatedLinMotorImpulse < m_maxLinMotorForce) { real_t desiredMotorVel = m_targetLinMotorVelocity; @@ -218,8 +218,8 @@ void SliderJoint3DSW::solve(real_t p_step) { m_accumulatedLinMotorImpulse = new_acc; // apply clamped impulse impulse_vector = normal * normalImpulse; - A->apply_impulse(m_relPosA, impulse_vector); - B->apply_impulse(m_relPosB, -impulse_vector); + A->apply_impulse(impulse_vector, m_relPosA); + B->apply_impulse(-impulse_vector, m_relPosB); } } } diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp index 1c2329f2dc..143cc9ebbd 100644 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -710,11 +710,11 @@ void PhysicsServer3DSW::body_add_central_force(RID p_body, const Vector3 &p_forc body->wakeup(); } -void PhysicsServer3DSW::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { +void PhysicsServer3DSW::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) { Body3DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->add_force(p_force, p_pos); + body->add_force(p_force, p_position); body->wakeup(); }; @@ -736,13 +736,13 @@ void PhysicsServer3DSW::body_apply_central_impulse(RID p_body, const Vector3 &p_ body->wakeup(); } -void PhysicsServer3DSW::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { +void PhysicsServer3DSW::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) { Body3DSW *body = body_owner.getornull(p_body); ERR_FAIL_COND(!body); _update_shapes(); - body->apply_impulse(p_pos, p_impulse); + body->apply_impulse(p_impulse, p_position); body->wakeup(); }; diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index 26230ef674..dccacb063f 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -206,11 +206,11 @@ public: virtual Vector3 body_get_applied_torque(RID p_body) const; virtual void body_add_central_force(RID p_body, const Vector3 &p_force); - virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos); + virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()); virtual void body_add_torque(RID p_body, const Vector3 &p_torque); virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse); - virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse); + virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()); virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity); diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 080b8c61ad..0dac08015f 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -91,11 +91,11 @@ void PhysicsDirectBodyState2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState2D::get_transform); ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState2D::add_central_force); - ClassDB::bind_method(D_METHOD("add_force", "offset", "force"), &PhysicsDirectBodyState2D::add_force); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState2D::add_force, Vector2()); ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState2D::add_torque); ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_central_impulse); ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_torque_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "offset", "impulse"), &PhysicsDirectBodyState2D::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicsDirectBodyState2D::apply_impulse, Vector2()); ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState2D::set_sleep_state); ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState2D::is_sleeping); @@ -132,13 +132,21 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape) { - ERR_FAIL_COND(p_shape.is_null()); - shape = p_shape->get_rid(); +void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + shape = p_shape_ref->get_rid(); +} + +RES PhysicsShapeQueryParameters2D::get_shape() const { + return shape_ref; } void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { - shape = p_shape; + if (shape != p_shape) { + shape_ref = RES(); + shape = p_shape; + } } RID PhysicsShapeQueryParameters2D::get_shape_rid() const { @@ -212,6 +220,7 @@ bool PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled() const { void PhysicsShapeQueryParameters2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters2D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters2D::get_shape); ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters2D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters2D::get_shape_rid); @@ -240,7 +249,7 @@ void PhysicsShapeQueryParameters2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); - //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); @@ -624,9 +633,9 @@ void PhysicsServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_central_impulse); ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_torque_impulse); - ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &PhysicsServer2D::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "impulse", "position"), &PhysicsServer2D::body_apply_impulse, Vector2()); ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer2D::body_add_central_force); - ClassDB::bind_method(D_METHOD("body_add_force", "body", "offset", "force"), &PhysicsServer2D::body_add_force); + ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer2D::body_add_force, Vector2()); ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer2D::body_add_torque); ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer2D::body_set_axis_velocity); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 549a78aa1f..e631046524 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -61,11 +61,11 @@ public: virtual Transform2D get_transform() const = 0; virtual void add_central_force(const Vector2 &p_force) = 0; - virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) = 0; + virtual void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0; virtual void add_torque(real_t p_torque) = 0; virtual void apply_central_impulse(const Vector2 &p_impulse) = 0; virtual void apply_torque_impulse(real_t p_torque) = 0; - virtual void apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse) = 0; + virtual void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) = 0; virtual void set_sleep_state(bool p_enable) = 0; virtual bool is_sleeping() const = 0; @@ -98,6 +98,8 @@ class PhysicsShapeQueryResult2D; class PhysicsShapeQueryParameters2D : public Reference { GDCLASS(PhysicsShapeQueryParameters2D, Reference); friend class PhysicsDirectSpaceState2D; + + RES shape_ref; RID shape; Transform2D transform; Vector2 motion; @@ -112,7 +114,8 @@ protected: static void _bind_methods(); public: - void set_shape(const RES &p_shape); + void set_shape(const RES &p_shape_ref); + RES get_shape() const; void set_shape_rid(const RID &p_shape); RID get_shape_rid() const; @@ -452,12 +455,12 @@ public: virtual float body_get_applied_torque(RID p_body) const = 0; virtual void body_add_central_force(RID p_body, const Vector2 &p_force) = 0; - virtual void body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force) = 0; + virtual void body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position = Vector2()) = 0; virtual void body_add_torque(RID p_body, float p_torque) = 0; virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) = 0; virtual void body_apply_torque_impulse(RID p_body, float p_torque) = 0; - virtual void body_apply_impulse(RID p_body, const Vector2 &p_offset, const Vector2 &p_impulse) = 0; + virtual void body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position = Vector2()) = 0; virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) = 0; //fix diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 9668358710..33a2b91902 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -92,12 +92,12 @@ void PhysicsDirectBodyState3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState3D::set_transform); ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState3D::get_transform); - ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState3D::add_central_force); - ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState3D::add_force); + ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState3D::add_central_force, Vector3()); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState3D::add_force, Vector3()); ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState3D::add_torque); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "j"), &PhysicsDirectBodyState3D::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "position", "j"), &PhysicsDirectBodyState3D::apply_impulse); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "j"), &PhysicsDirectBodyState3D::apply_torque_impulse); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicsDirectBodyState3D::apply_central_impulse, Vector3()); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &PhysicsDirectBodyState3D::apply_impulse, Vector3()); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &PhysicsDirectBodyState3D::apply_torque_impulse); ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState3D::set_sleep_state); ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState3D::is_sleeping); @@ -136,13 +136,21 @@ PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {} /////////////////////////////////////////////////////// -void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape) { - ERR_FAIL_COND(p_shape.is_null()); - shape = p_shape->get_rid(); +void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape_ref) { + ERR_FAIL_COND(p_shape_ref.is_null()); + shape_ref = p_shape_ref; + shape = p_shape_ref->get_rid(); +} + +RES PhysicsShapeQueryParameters3D::get_shape() const { + return shape_ref; } void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) { - shape = p_shape; + if (shape != p_shape) { + shape_ref = RES(); + shape = p_shape; + } } RID PhysicsShapeQueryParameters3D::get_shape_rid() const { @@ -208,6 +216,7 @@ bool PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled() const { void PhysicsShapeQueryParameters3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters3D::set_shape); + ClassDB::bind_method(D_METHOD("get_shape"), &PhysicsShapeQueryParameters3D::get_shape); ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters3D::set_shape_rid); ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters3D::get_shape_rid); @@ -232,7 +241,7 @@ void PhysicsShapeQueryParameters3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); - //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape3D"), "set_shape", "get_shape"); ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); @@ -486,11 +495,11 @@ void PhysicsServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer3D::body_get_state); ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer3D::body_add_central_force); - ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer3D::body_add_force); + ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer3D::body_add_force, Vector3()); ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer3D::body_add_torque); ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_central_impulse); - ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &PhysicsServer3D::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "impulse", "position"), &PhysicsServer3D::body_apply_impulse, Vector3()); ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_torque_impulse); ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer3D::body_set_axis_velocity); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index 2465b40d3e..dcb183aea4 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -63,11 +63,11 @@ public: virtual Transform get_transform() const = 0; virtual void add_central_force(const Vector3 &p_force) = 0; - virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) = 0; + virtual void add_force(const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0; virtual void add_torque(const Vector3 &p_torque) = 0; - virtual void apply_central_impulse(const Vector3 &p_j) = 0; - virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) = 0; - virtual void apply_torque_impulse(const Vector3 &p_j) = 0; + virtual void apply_central_impulse(const Vector3 &p_impulse) = 0; + virtual void apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) = 0; + virtual void apply_torque_impulse(const Vector3 &p_impulse) = 0; virtual void set_sleep_state(bool p_sleep) = 0; virtual bool is_sleeping() const = 0; @@ -100,6 +100,7 @@ class PhysicsShapeQueryParameters3D : public Reference { GDCLASS(PhysicsShapeQueryParameters3D, Reference); friend class PhysicsDirectSpaceState3D; + RES shape_ref; RID shape; Transform transform; float margin; @@ -113,7 +114,8 @@ protected: static void _bind_methods(); public: - void set_shape(const RES &p_shape); + void set_shape(const RES &p_shape_ref); + RES get_shape() const; void set_shape_rid(const RID &p_shape); RID get_shape_rid() const; @@ -429,11 +431,11 @@ public: virtual Vector3 body_get_applied_torque(RID p_body) const = 0; virtual void body_add_central_force(RID p_body, const Vector3 &p_force) = 0; - virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) = 0; + virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position = Vector3()) = 0; virtual void body_add_torque(RID p_body, const Vector3 &p_torque) = 0; virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) = 0; - virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) = 0; + virtual void body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position = Vector3()) = 0; virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) = 0; virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) = 0; diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index 026725bf01..348fc423bb 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -32,10 +32,9 @@ #define RASTERIZER_H #include "core/math/camera_matrix.h" -#include "servers/rendering_server.h" - #include "core/pair.h" #include "core/self_list.h" +#include "servers/rendering_server.h" class RasterizerScene { public: @@ -50,6 +49,16 @@ public: virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; virtual void set_directional_shadow_count(int p_count) = 0; + /* SDFGI UPDATE */ + + struct InstanceBase; + + virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0; + virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0; + virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0; + virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0; + virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) = 0; + /* SKY API */ virtual RID sky_create() = 0; @@ -86,6 +95,11 @@ public: virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; + virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0; + virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0; + virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; @@ -111,8 +125,6 @@ public: virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0; virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0; - struct InstanceBase; - struct InstanceDependency { void instance_notify_changed(bool p_aabb, bool p_dependencies); void instance_notify_deleted(RID p_deleted); @@ -248,6 +260,7 @@ public: virtual RID light_instance_create(RID p_light) = 0; virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0; + virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0; virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0; virtual void light_instance_mark_visible(RID p_light_instance) = 0; virtual bool light_instances_can_render_shadow_cube() const { @@ -273,10 +286,14 @@ public: virtual bool gi_probe_needs_update(RID p_probe) const = 0; virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0; + virtual void gi_probe_set_quality(RS::GIProbeQuality) = 0; + virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0; virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) = 0; + virtual void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) = 0; virtual void set_scene_pass(uint64_t p_pass) = 0; virtual void set_time(double p_time, double p_step) = 0; @@ -285,7 +302,7 @@ public: virtual RID render_buffers_create() = 0; virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa) = 0; - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; virtual bool screen_space_roughness_limiter_is_active() const = 0; virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0; @@ -295,6 +312,8 @@ public: virtual bool free(RID p_rid) = 0; + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0; + virtual void update() = 0; virtual ~RasterizerScene() {} }; @@ -484,7 +503,8 @@ public: virtual void light_set_negative(RID p_light, bool p_enable) = 0; virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; - virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; + virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) = 0; + virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0; @@ -503,7 +523,8 @@ public: virtual AABB light_get_aabb(RID p_light) const = 0; virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0; virtual Color light_get_color(RID p_light) = 0; - virtual bool light_get_use_gi(RID p_light) = 0; + virtual RS::LightBakeMode light_get_bake_mode(RID p_light) = 0; + virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0; virtual uint64_t light_get_version(RID p_light) const = 0; /* PROBE API */ @@ -513,9 +534,9 @@ public: virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0; virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; - virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) = 0; - virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0; - virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0; + virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) = 0; + virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0; + virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp index 4c477ca5f4..aad2be45c6 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp @@ -2497,7 +2497,7 @@ RasterizerCanvasRD::~RasterizerCanvasRD() { _dispose_bindings(); //anything remains? if (bindings.texture_bindings.size()) { - ERR_PRINT("Some texture bindings were not properly freed (leaked canvasitems?"); + ERR_PRINT("Some texture bindings were not properly freed (leaked CanvasItems?)"); const TextureBindingID *key = nullptr; while ((key = bindings.texture_bindings.next(key))) { TextureBinding *tb = bindings.texture_bindings[*key]; diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp index 303cb7ad42..3f594ab264 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp @@ -218,7 +218,7 @@ void RasterizerEffectsRD::copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_f RD::get_singleton()->draw_list_draw(draw_list, true); } -void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero) { +void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_alpha_to_zero, bool p_srgb, RID p_secondary) { zeromem(©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); if (p_flip_y) { @@ -230,10 +230,16 @@ void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_fr if (p_alpha_to_zero) { copy_to_fb.push_constant.alpha_to_zero = true; } + if (p_srgb) { + copy_to_fb.push_constant.srgb = true; + } RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[p_secondary.is_valid() ? COPY_TO_FB_COPY2 : COPY_TO_FB_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + if (p_secondary.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_secondary), 1); + } RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); RD::get_singleton()->draw_list_set_push_constant(draw_list, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant)); RD::get_singleton()->draw_list_draw(draw_list, true); @@ -434,7 +440,7 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { +void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); int32_t x_groups = (p_screen_size.width - 1) / 8 + 1; @@ -451,7 +457,7 @@ void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, R RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal_roughness), 1); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3); @@ -491,7 +497,7 @@ void RasterizerEffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal, R if (p_roughness_quality != RS::ENV_SSR_ROUGNESS_QUALITY_DISABLED) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_metallic, p_roughness), 3); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_metallic, p_normal_roughness), 3); } else { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3); @@ -1201,6 +1207,28 @@ void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_ RD::get_singleton()->draw_list_draw(draw_list, true); } +void RasterizerEffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples) { + ResolvePushConstant push_constant; + push_constant.screen_size[0] = p_screen_size.x; + push_constant.screen_size[1] = p_screen_size.y; + push_constant.samples = p_samples; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_giprobe.is_valid() ? RESOLVE_MODE_GI_GIPROBE : RESOLVE_MODE_GI]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_source_depth, p_source_normal_roughness), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_dest_depth, p_dest_normal_roughness), 1); + if (p_source_giprobe.is_valid()) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_giprobe), 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_giprobe), 3); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1, 8, 8, 1); + + RD::get_singleton()->compute_list_end(); +} + RasterizerEffectsRD::RasterizerEffectsRD() { { // Initialize copy Vector<String> copy_modes; @@ -1228,6 +1256,7 @@ RasterizerEffectsRD::RasterizerEffectsRD() { Vector<String> copy_modes; copy_modes.push_back("\n"); copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); + copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); copy_to_fb.shader.initialize(copy_modes); @@ -1517,6 +1546,20 @@ RasterizerEffectsRD::RasterizerEffectsRD() { } } + { + Vector<String> resolve_modes; + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define GIPROBE_RESOLVE\n"); + + resolve.shader.initialize(resolve_modes); + + resolve.shader_version = resolve.shader.version_create(); + + for (int i = 0; i < RESOLVE_MODE_MAX; i++) { + resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i)); + } + } + RD::SamplerState sampler; sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; @@ -1569,6 +1612,7 @@ RasterizerEffectsRD::~RasterizerEffectsRD() { cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version); filter.shader.version_free(filter.shader_version); luminance_reduce.shader.version_free(luminance_reduce.shader_version); + resolve.shader.version_free(resolve.shader_version); roughness.shader.version_free(roughness.shader_version); roughness_limiter.shader.version_free(roughness_limiter.shader_version); specular_merge.shader.version_free(specular_merge.shader_version); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h index 8a55d2d13c..80849654de 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h @@ -41,6 +41,7 @@ #include "servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/resolve.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/screen_space_reflection_filter.glsl.gen.h" @@ -114,6 +115,7 @@ class RasterizerEffectsRD { enum CopyToFBMode { COPY_TO_FB_COPY, COPY_TO_FB_COPY_PANORAMA_TO_DP, + COPY_TO_FB_COPY2, COPY_TO_FB_MAX, }; @@ -126,7 +128,8 @@ class RasterizerEffectsRD { uint32_t force_luminance; uint32_t alpha_to_zero; - uint32_t pad[2]; + uint32_t srgb; + uint32_t pad; }; struct CopyToFb { @@ -512,6 +515,25 @@ class RasterizerEffectsRD { RID pipelines[3]; //3 quality levels } sss; + struct ResolvePushConstant { + int32_t screen_size[2]; + int32_t samples; + uint32_t pad; + }; + + enum ResolveMode { + RESOLVE_MODE_GI, + RESOLVE_MODE_GI_GIPROBE, + RESOLVE_MODE_MAX + }; + + struct Resolve { + ResolvePushConstant push_constant; + ResolveShaderRD shader; + RID shader_version; + RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels + } resolve; + RID default_sampler; RID default_mipmap_sampler; RID index_buffer; @@ -544,7 +566,7 @@ class RasterizerEffectsRD { RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2); public: - void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false); + void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID()); void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false); void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); @@ -605,10 +627,12 @@ public: void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array); void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position); - void screen_space_reflection(RID p_diffuse, RID p_normal, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_roughness, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera); + void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera); void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection); void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); + void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_giprobe, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_giprobe, Vector2i p_screen_size, int p_samples); + RasterizerEffectsRD(); ~RasterizerEffectsRD(); }; diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.h b/servers/rendering/rasterizer_rd/rasterizer_rd.h index cb53a531ac..cdcc6bfd73 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_rd.h @@ -74,6 +74,7 @@ public: _ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; } _ALWAYS_INLINE_ float get_frame_delta_time() const { return delta; } + _ALWAYS_INLINE_ double get_total_time() const { return time; } static Error is_viable() { return OK; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index 7d351f249a..890ada019f 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -268,8 +268,8 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { blend_state_blend.attachments.push_back(blend_attachment); RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1); RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2); - RD::PipelineColorBlendState blend_state_depth_normal = RD::PipelineColorBlendState::create_disabled(1); - RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(2); + RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1); + RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2); //update pipelines @@ -310,12 +310,12 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; if (uses_alpha || uses_blend_alpha) { - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { blend_state = blend_state_blend; if (depth_draw == DEPTH_DRAW_OPAQUE) { depth_stencil.enable_depth_write = false; //alpha does not draw depth } - } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) { + } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) { if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { //none, blend state contains nothing } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { @@ -328,20 +328,23 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { continue; // do not use this version (will error if using it is attempted) } } else { - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { blend_state = blend_state_opaque; } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { //none, leave empty - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL) { - blend_state = blend_state_depth_normal; } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { blend_state = blend_state_depth_normal_roughness; + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) { + blend_state = blend_state_depth_normal_roughness_giprobe; } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) { + blend_state = RD::PipelineColorBlendState(); //no color targets for SDF } else { //specular write blend_state = blend_state_opaque_specular; + depth_stencil.enable_depth_test = false; + depth_stencil.enable_depth_write = false; } } @@ -607,7 +610,78 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() { } } +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_gi() { + if (!reflection_buffer.is_valid()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = width; + tf.height = height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } +} + +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_giprobe() { + if (!giprobe_buffer.is_valid()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8_UINT; + tf.width = width; + tf.height = height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + + if (msaa != RS::VIEWPORT_MSAA_DISABLED) { + RD::TextureFormat tf_aa = tf; + tf_aa.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tf_aa.samples = texture_samples; + giprobe_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView()); + } else { + tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } + + tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; + + giprobe_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector<RID> fb; + if (msaa != RS::VIEWPORT_MSAA_DISABLED) { + fb.push_back(depth_msaa); + fb.push_back(normal_roughness_buffer_msaa); + fb.push_back(giprobe_buffer_msaa); + } else { + fb.push_back(depth); + fb.push_back(normal_roughness_buffer); + fb.push_back(giprobe_buffer); + } + + depth_normal_roughness_giprobe_fb = RD::get_singleton()->framebuffer_create(fb); + } +} + void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { + if (ambient_buffer != RID() && ambient_buffer != color) { + RD::get_singleton()->free(ambient_buffer); + ambient_buffer = RID(); + } + + if (reflection_buffer != RID() && reflection_buffer != specular) { + RD::get_singleton()->free(reflection_buffer); + reflection_buffer = RID(); + } + + if (giprobe_buffer != RID()) { + RD::get_singleton()->free(giprobe_buffer); + giprobe_buffer = RID(); + + if (giprobe_buffer_msaa.is_valid()) { + RD::get_singleton()->free(giprobe_buffer_msaa); + giprobe_buffer_msaa = RID(); + } + + depth_normal_roughness_giprobe_fb = RID(); + } + if (color_msaa.is_valid()) { RD::get_singleton()->free(color_msaa); color_msaa = RID(); @@ -634,24 +708,18 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { color_fb = RID(); depth_fb = RID(); - if (normal_buffer.is_valid()) { - RD::get_singleton()->free(normal_buffer); - if (normal_buffer_msaa.is_valid()) { - RD::get_singleton()->free(normal_buffer_msaa); - normal_buffer_msaa = RID(); + if (normal_roughness_buffer.is_valid()) { + RD::get_singleton()->free(normal_roughness_buffer); + if (normal_roughness_buffer_msaa.is_valid()) { + RD::get_singleton()->free(normal_roughness_buffer_msaa); + normal_roughness_buffer_msaa = RID(); } - normal_buffer = RID(); - depth_normal_fb = RID(); + normal_roughness_buffer = RID(); + depth_normal_roughness_fb = RID(); } - if (roughness_buffer.is_valid()) { - RD::get_singleton()->free(roughness_buffer); - if (roughness_buffer_msaa.is_valid()) { - RD::get_singleton()->free(roughness_buffer_msaa); - roughness_buffer_msaa = RID(); - } - roughness_buffer = RID(); - depth_normal_roughness_fb = RID(); + if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) { + RD::get_singleton()->free(render_sdfgi_uniform_set); } } @@ -686,7 +754,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_bu tf.width = p_width; tf.height = p_height; tf.type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = { RD::TEXTURE_SAMPLES_1, @@ -702,7 +770,7 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_bu color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -722,80 +790,38 @@ void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_bu } } -void RasterizerSceneHighEndRD::_allocate_normal_texture(RenderBufferDataHighEnd *rb) { - if (rb->normal_buffer.is_valid()) { +void RasterizerSceneHighEndRD::_allocate_normal_roughness_texture(RenderBufferDataHighEnd *rb) { + if (rb->normal_roughness_buffer.is_valid()) { return; } RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tf.width = rb->width; tf.height = rb->height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - } else { - tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - } - - rb->normal_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) { - Vector<RID> fb; - fb.push_back(rb->depth); - fb.push_back(rb->normal_buffer); - rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); - } else { - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - tf.samples = rb->texture_samples; - rb->normal_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - Vector<RID> fb; - fb.push_back(rb->depth_msaa); - fb.push_back(rb->normal_buffer_msaa); - rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); - } - - _render_buffers_clear_uniform_set(rb); -} - -void RasterizerSceneHighEndRD::_allocate_roughness_texture(RenderBufferDataHighEnd *rb) { - if (rb->roughness_buffer.is_valid()) { - return; - } - - ERR_FAIL_COND(rb->normal_buffer.is_null()); - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; } else { tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } - rb->roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->normal_roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) { Vector<RID> fb; fb.push_back(rb->depth); - fb.push_back(rb->normal_buffer); - fb.push_back(rb->roughness_buffer); + fb.push_back(rb->normal_roughness_buffer); rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); } else { - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; tf.samples = rb->texture_samples; - rb->roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->normal_roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); Vector<RID> fb; fb.push_back(rb->depth_msaa); - fb.push_back(rb->normal_buffer_msaa); - fb.push_back(rb->roughness_buffer_msaa); + fb.push_back(rb->normal_roughness_buffer_msaa); rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); } @@ -813,7 +839,7 @@ bool RasterizerSceneHighEndRD::free(RID p_rid) { return false; } -void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth) { +void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi, bool p_has_opaque_gi) { uint32_t lightmap_captures_used = 0; for (int i = 0; i < p_element_count; i++) { @@ -855,37 +881,7 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, continue; } - if (!e->instance->gi_probe_instances.empty()) { - uint32_t written = 0; - for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) { - RID probe = e->instance->gi_probe_instances[j]; - int slot = gi_probe_instance_get_slot(probe); - if (slot < 0) { - continue; //unallocated, dont render - } - - if (render_pass != gi_probe_instance_get_render_pass(probe)) { - continue; //not rendered in this frame - } - - uint32_t index = gi_probe_instance_get_render_index(probe); - - if (written == 0) { - id.gi_offset = index; - id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE; - written = 1; - } else { - id.gi_offset = index << 16; - written = 2; - break; - } - } - if (written == 0) { - id.gi_offset = 0xFFFFFFFF; - } else if (written == 1) { - id.gi_offset |= 0xFFFF0000; - } - } else if (e->instance->lightmap) { + if (e->instance->lightmap) { int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base); if (lightmap_index >= 0) { id.gi_offset = lightmap_index; @@ -916,8 +912,40 @@ void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, id.gi_offset = lightmap_captures_used; lightmap_captures_used++; } + } else { - id.gi_offset = 0xFFFFFFFF; + if (p_has_opaque_gi) { + id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS; + } + + if (!e->instance->gi_probe_instances.empty()) { + uint32_t written = 0; + for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) { + RID probe = e->instance->gi_probe_instances[j]; + + uint32_t index = gi_probe_instance_get_render_index(probe); + + if (written == 0) { + id.gi_offset = index; + id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE; + written = 1; + } else { + id.gi_offset = index << 16; + written = 2; + break; + } + } + if (written == 0) { + id.gi_offset = 0xFFFFFFFF; + } else if (written == 1) { + id.gi_offset |= 0xFFFF0000; + } + } else { + if (p_has_sdfgi && (e->instance->baked_light || e->instance->dynamic_gi)) { + id.flags |= INSTANCE_DATA_FLAG_USE_SDFGI; + } + id.gi_offset = 0xFFFFFFFF; + } } } @@ -970,7 +998,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l //find cull variant ShaderData::CullVariant cull_variant; - if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) { + if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) { cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED; } else { bool mirror = e->instance->mirror; @@ -1016,8 +1044,8 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l case PASS_MODE_COLOR_TRANSPARENT: { if (e->uses_lightmap) { shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS; - } else if (e->uses_vct) { - shader_version = SHADER_VERSION_VCT_COLOR_PASS; + } else if (e->uses_forward_gi) { + shader_version = SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI; } else { shader_version = SHADER_VERSION_COLOR_PASS; } @@ -1025,8 +1053,6 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l case PASS_MODE_COLOR_SPECULAR: { if (e->uses_lightmap) { shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR; - } else if (e->uses_vct) { - shader_version = SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR; } else { shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR; } @@ -1038,15 +1064,18 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l case PASS_MODE_SHADOW_DP: { shader_version = SHADER_VERSION_DEPTH_PASS_DP; } break; - case PASS_MODE_DEPTH_NORMAL: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL; - } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { + shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE; + } break; case PASS_MODE_DEPTH_MATERIAL: { shader_version = SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; } break; + case PASS_MODE_SDF: { + shader_version = SHADER_VERSION_DEPTH_PASS_WITH_SDF; + } break; } RenderPipelineVertexFormatCacheRD *pipeline = nullptr; @@ -1134,7 +1163,7 @@ void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_l } } -void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_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) { +void RasterizerSceneHighEndRD::_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 Size2 &p_screen_pixel_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) { //CameraMatrix projection = p_cam_projection; //projection.flip_y(); // Vulkan and modern APIs use Y-Down CameraMatrix correction; @@ -1178,6 +1207,70 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer //time global variables scene_state.ubo.time = time; + scene_state.ubo.gi_upscale_for_msaa = false; + + if (p_render_buffers.is_valid()) { + RenderBufferDataHighEnd *render_buffers = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) { + scene_state.ubo.gi_upscale_for_msaa = true; + } + } +#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); + 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); + 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); + + 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]; + + //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; + + uint32_t oct_size = sdfgi_get_lightprobe_octahedron_size(); + + scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size * scene_state.ubo.sdfgi_probe_axis_size); + scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[1] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size); + scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[2] = 1.0; + + scene_state.ubo.sdfgi_probe_uv_offset[0] = float(oct_size + 2) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0]; + scene_state.ubo.sdfgi_probe_uv_offset[1] = float(oct_size + 2) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[1]; + scene_state.ubo.sdfgi_probe_uv_offset[2] = float((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0]; + + scene_state.ubo.sdfgi_occlusion_renormalize[0] = 0.5; + scene_state.ubo.sdfgi_occlusion_renormalize[1] = 1.0; + scene_state.ubo.sdfgi_occlusion_renormalize[2] = 1.0 / float(scene_state.ubo.sdfgi_cascade_count); + + 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 + 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); + + Vector3i probe_ofs = render_buffers_get_sdfgi_cascade_probe_offset(p_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; + } + } +#endif if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { scene_state.ubo.use_ambient_light = true; scene_state.ubo.ambient_light_color_energy[0] = 1; @@ -1260,11 +1353,13 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const Camer } scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active(); + scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount(); + scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit(); RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true); } -void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) { +void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) { RID m_src; m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material; @@ -1293,18 +1388,18 @@ void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t ERR_FAIL_COND(!material); - _add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index); + _add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index, p_using_sdfgi); while (material->next_pass.is_valid()) { material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D); if (!material || !material->shader_data->valid) { break; + _add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index, p_using_sdfgi); } - _add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index); } } -void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index) { +void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) { bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; @@ -1332,13 +1427,11 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta return; } - if (p_pass_mode != PASS_MODE_DEPTH_MATERIAL && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { + if ((p_pass_mode != PASS_MODE_DEPTH_MATERIAL && p_pass_mode != PASS_MODE_SDF) && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { //shader does not use discard and does not write a vertex position, use generic material if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) { p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL && !p_material->shader_data->uses_normal) { - p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) { + } else if ((p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) { p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); } } @@ -1346,7 +1439,9 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta has_alpha = false; } - RenderList::Element *e = (has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) ? render_list.add_alpha_element() : render_list.add_element(); + has_alpha = has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED; + + RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); if (!e) { return; @@ -1373,7 +1468,7 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta e->material_index = e->material->index; e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH; e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.empty(); - e->uses_vct = e->instance->gi_probe_instances.size(); + e->uses_forward_gi = has_alpha && (e->instance->gi_probe_instances.size() || p_using_sdfgi); e->shader_index = e->shader_index; e->depth_layer = e->instance->depth_layer; e->priority = p_material->priority; @@ -1383,7 +1478,7 @@ void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_insta } } -void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi) { +void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi) { scene_state.current_shader_index = 0; scene_state.current_material_index = 0; scene_state.used_sss = false; @@ -1415,7 +1510,7 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j]; uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index); - _add_geometry(inst, j, material, p_pass_mode, surface_index); + _add_geometry(inst, j, material, p_pass_mode, surface_index, p_using_sdfgi); } //mesh->last_pass=frame; @@ -1443,7 +1538,7 @@ void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, i for (uint32_t j = 0; j < surface_count; j++) { uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index); - _add_geometry(inst, j, materials[j], p_pass_mode, surface_index); + _add_geometry(inst, j, materials[j], p_pass_mode, surface_index, p_using_sdfgi); } } break; @@ -1525,30 +1620,13 @@ void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_r reflection_ubo.params[2] = interior ? 1.0 : 0.0; reflection_ubo.params[3] = box_projection ? 1.0 : 0.0; - if (interior) { - Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear(); - float interior_ambient_energy = storage->reflection_probe_get_interior_ambient_energy(base_probe); - float interior_ambient_probe_contrib = storage->reflection_probe_get_interior_ambient_probe_contribution(base_probe); - reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy; - reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy; - reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy; - reflection_ubo.ambient[3] = interior_ambient_probe_contrib; - } else { - Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear(); - if (is_environment(p_environment)) { - Color env_ambient_color = environment_get_ambient_light_color(p_environment).to_linear(); - float env_ambient_energy = environment_get_ambient_light_energy(p_environment); - ambient_linear = env_ambient_color; - ambient_linear.r *= env_ambient_energy; - ambient_linear.g *= env_ambient_energy; - ambient_linear.b *= env_ambient_energy; - } - - reflection_ubo.ambient[0] = ambient_linear.r; - reflection_ubo.ambient[1] = ambient_linear.g; - reflection_ubo.ambient[2] = ambient_linear.b; - reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light - } + Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear(); + float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe); + uint32_t ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe); + reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy; + reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy; + reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy; + reflection_ubo.ambient_mode = ambient_mode; Transform transform = reflection_probe_instance_get_transform(rpi); Transform proj = (p_camera_inverse_transform * transform).inverse(); @@ -1583,59 +1661,6 @@ void RasterizerSceneHighEndRD::_setup_lightmaps(InstanceBase **p_lightmap_cull_r } } -void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) { - int index = 0; - - for (int i = 0; i < p_gi_probe_probe_cull_count; i++) { - RID rpi = p_gi_probe_probe_cull_result[i]; - - if (index >= (int)scene_state.max_gi_probes) { - continue; - } - - int slot = gi_probe_instance_get_slot(rpi); - if (slot < 0) { - continue; //not usable - } - - RID base_probe = gi_probe_instance_get_base_probe(rpi); - - GIProbeData &gi_probe_ubo = scene_state.gi_probes[index]; - - Transform to_cell = gi_probe_instance_get_transform_to_cell(rpi) * p_camera_transform; - - store_transform(to_cell, gi_probe_ubo.xform); - - Vector3 bounds = storage->gi_probe_get_octree_size(base_probe); - - gi_probe_ubo.bounds[0] = bounds.x; - gi_probe_ubo.bounds[1] = bounds.y; - gi_probe_ubo.bounds[2] = bounds.z; - - gi_probe_ubo.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe); - gi_probe_ubo.bias = storage->gi_probe_get_bias(base_probe); - gi_probe_ubo.normal_bias = storage->gi_probe_get_normal_bias(base_probe); - gi_probe_ubo.blend_ambient = !storage->gi_probe_is_interior(base_probe); - gi_probe_ubo.texture_slot = gi_probe_instance_get_slot(rpi); - gi_probe_ubo.anisotropy_strength = storage->gi_probe_get_anisotropy_strength(base_probe); - gi_probe_ubo.ao = storage->gi_probe_get_ao(base_probe); - gi_probe_ubo.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f); - - if (gi_probe_is_anisotropic()) { - gi_probe_ubo.texture_slot *= 3; - } - - gi_probe_instance_set_render_index(rpi, index); - gi_probe_instance_set_render_pass(rpi, render_pass); - - index++; - } - - if (index) { - RD::get_singleton()->buffer_update(scene_state.gi_probe_buffer, 0, index * sizeof(GIProbeData), scene_state.gi_probes, true); - } -} - void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows) { uint32_t light_count = 0; scene_state.ubo.directional_light_count = 0; @@ -2156,6 +2181,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor Vector<Color> depth_pass_clear; bool using_separate_specular = false; bool using_ssr = false; + bool using_sdfgi = false; + bool using_giprobe = false; if (render_buffer) { screen_pixel_size.width = 1.0 / render_buffer->width; @@ -2165,43 +2192,55 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor opaque_framebuffer = render_buffer->color_fb; - if (p_environment.is_valid() && environment_is_ssr_enabled(p_environment)) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; - render_buffer->ensure_specular(); - using_separate_specular = true; - using_ssr = true; - opaque_specular_framebuffer = render_buffer->color_specular_fb; - } else if (screen_space_roughness_limiter_is_active()) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL; - //we need to allocate both these, if not allocated - _allocate_normal_texture(render_buffer); - _allocate_roughness_texture(render_buffer); + if (p_gi_probe_cull_count > 0) { + using_giprobe = true; + render_buffer->ensure_gi(); + } + + if (!p_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)) { + depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also giprobe + using_sdfgi = true; + render_buffer->ensure_gi(); + } else { + depth_pass_mode = using_giprobe ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; + } + + if (environment_is_ssr_enabled(p_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)) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL; + depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; } switch (depth_pass_mode) { case PASS_MODE_DEPTH: { depth_framebuffer = render_buffer->depth_fb; } break; - case PASS_MODE_DEPTH_NORMAL: { - _allocate_normal_texture(render_buffer); - depth_framebuffer = render_buffer->depth_normal_fb; - depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); - } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { - _allocate_normal_texture(render_buffer); - _allocate_roughness_texture(render_buffer); + _allocate_normal_roughness_texture(render_buffer); depth_framebuffer = render_buffer->depth_normal_roughness_fb; depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); - depth_pass_clear.push_back(Color()); + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { + _allocate_normal_roughness_texture(render_buffer); + render_buffer->ensure_giprobe(); + depth_framebuffer = render_buffer->depth_normal_roughness_giprobe_fb; + depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + depth_pass_clear.push_back(Color(0, 0, 0, 0)); } break; default: { }; } alpha_framebuffer = opaque_framebuffer; - } else if (p_reflection_probe.is_valid()) { uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe); screen_pixel_size.width = 1.0 / resolution; @@ -2216,7 +2255,6 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { p_environment = RID(); //no environment on interiors } - } else { ERR_FAIL(); //bug? } @@ -2226,16 +2264,15 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows); _setup_decals(p_decal_cull_result, p_decal_cull_count, p_cam_transform.affine_inverse()); _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment); - _setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform); _setup_lightmaps(p_lightmap_cull_result, p_lightmap_cull_count, p_cam_transform); - _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_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_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_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); cluster_builder.bake_cluster(); //bake to cluster _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr); + _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, using_sdfgi); bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; @@ -2307,47 +2344,46 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor clear_color = p_default_bg_color; } - _setup_view_dependant_uniform_set(p_shadow_atlas, p_reflection_atlas); + _setup_view_dependant_uniform_set(p_shadow_atlas, p_reflection_atlas, p_gi_probe_cull_result, p_gi_probe_cull_count); render_list.sort_by_key(false); - _fill_instances(render_list.elements, render_list.element_count, false); + _fill_instances(render_list.elements, render_list.element_count, false, false, using_sdfgi || using_giprobe); bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION; + bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; bool depth_pre_pass = depth_framebuffer.is_valid(); RID render_buffers_uniform_set; bool using_ssao = depth_pre_pass && p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment); - + bool continue_depth = false; if (depth_pre_pass) { //depth pre pass RENDER_TIMESTAMP("Render Depth Pre-Pass"); - bool finish_depth = using_ssao; + bool finish_depth = using_ssao || using_sdfgi || using_giprobe; RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear); _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID(), get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); RD::get_singleton()->draw_list_end(); if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - if (finish_depth) { + if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) { + static int texture_samples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8, 16 }; + storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_giprobe ? render_buffer->giprobe_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_giprobe ? render_buffer->giprobe_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_samples[render_buffer->msaa]); + } else if (finish_depth) { RD::get_singleton()->texture_resolve_multisample(render_buffer->depth_msaa, render_buffer->depth, true); } - - if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->normal_buffer_msaa, render_buffer->normal_buffer, true); - if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->roughness_buffer_msaa, render_buffer->roughness_buffer, true); - } - } } + + continue_depth = !finish_depth; } if (using_ssao) { - _process_ssao(p_render_buffer, p_environment, render_buffer->normal_buffer, p_cam_projection); + _process_ssao(p_render_buffer, p_environment, render_buffer->normal_roughness_buffer, p_cam_projection); } - if (p_render_buffer.is_valid() && screen_space_roughness_limiter_is_active()) { - storage->get_effects()->roughness_limit(render_buffer->normal_buffer, render_buffer->roughness_buffer, Size2(render_buffer->width, render_buffer->height), screen_space_roughness_limiter_get_curve()); + if (using_sdfgi || using_giprobe) { + _process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count); } if (p_render_buffer.is_valid()) { @@ -2356,7 +2392,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor render_buffers_uniform_set = render_buffer->uniform_set; } - _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_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_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_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()); RENDER_TIMESTAMP("Render Opaque Pass"); @@ -2364,8 +2400,8 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss; { - bool will_continue_color = (can_continue_color || draw_sky || debug_giprobes); - bool will_continue_depth = (can_continue_depth || draw_sky || debug_giprobes); + bool will_continue_color = (can_continue_color || draw_sky || debug_giprobes || debug_sdfgi_probes); + bool will_continue_depth = (can_continue_depth || draw_sky || debug_giprobes || debug_sdfgi_probes); //regular forward for now Vector<Color> c; @@ -2379,7 +2415,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor } RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer; - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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 ? (using_ssao ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); RD::get_singleton()->draw_list_end(); @@ -2405,6 +2441,19 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor RD::get_singleton()->draw_list_end(); } + if (debug_sdfgi_probes) { + //debug giprobes + bool will_continue_color = (can_continue_color || draw_sky); + bool will_continue_depth = (can_continue_depth || draw_sky); + + CameraMatrix dc; + dc.set_depth_correction(true); + CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_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); + _debug_sdfgi_probes(p_render_buffer, draw_list, opaque_framebuffer, cm); + RD::get_singleton()->draw_list_end(); + } + if (draw_sky) { RENDER_TIMESTAMP("Render Sky"); @@ -2437,7 +2486,7 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor if (using_ssr) { RENDER_TIMESTAMP("Screen Space Reflection"); - _process_ssr(p_render_buffer, render_buffer->color_fb, render_buffer->normal_buffer, render_buffer->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_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); } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); @@ -2447,11 +2496,11 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor RENDER_TIMESTAMP("Render Transparent Pass"); - _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_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_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_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); render_list.sort_by_reverse_depth_and_priority(true); - _fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false); + _fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, using_sdfgi); { RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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); @@ -2473,15 +2522,15 @@ void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase ** scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; - _setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake); + _setup_environment(RID(), RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar, false, p_use_pancake); render_list.clear(); PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW; - _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); + _fill_render_list(p_cull_result, p_cull_count, pass_mode); - _setup_view_dependant_uniform_set(RID(), RID()); + _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); RENDER_TIMESTAMP("Render Shadow"); @@ -2507,14 +2556,14 @@ void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = true; - _setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); + _setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); render_list.clear(); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); + _fill_render_list(p_cull_result, p_cull_count, pass_mode); - _setup_view_dependant_uniform_set(RID(), RID()); + _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); RENDER_TIMESTAMP("Render Material"); @@ -2546,14 +2595,14 @@ void RasterizerSceneHighEndRD::_render_uv2(InstanceBase **p_cull_result, int p_c scene_state.ubo.dual_paraboloid_side = 0; scene_state.ubo.material_uv2_mode = true; - _setup_environment(RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); + _setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); render_list.clear(); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); + _fill_render_list(p_cull_result, p_cull_count, pass_mode); - _setup_view_dependant_uniform_set(RID(), RID()); + _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); RENDER_TIMESTAMP("Render Material"); @@ -2597,6 +2646,121 @@ void RasterizerSceneHighEndRD::_render_uv2(InstanceBase **p_cull_result, int p_c } } +void RasterizerSceneHighEndRD::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { + RENDER_TIMESTAMP("Render SDFGI"); + + _update_render_base_uniform_set(); + + RenderBufferDataHighEnd *render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + ERR_FAIL_COND(!render_buffer); + + render_pass++; + render_list.clear(); + + PassMode pass_mode = PASS_MODE_SDF; + _fill_render_list(p_cull_result, p_cull_count, pass_mode); + render_list.sort_by_key(false); + _fill_instances(render_list.elements, render_list.element_count, true); + + _setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); + + Vector3 half_extents = p_bounds.size * 0.5; + Vector3 center = p_bounds.position + half_extents; + + if (render_buffer->render_sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_buffer->render_sdfgi_uniform_set)) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(p_albedo_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(p_emission_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(p_emission_aniso_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.ids.push_back(p_geom_facing_texture); + uniforms.push_back(u); + } + + render_buffer->render_sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_sdfgi_rd, RENDER_BUFFERS_UNIFORM_SET); + } + + Vector<RID> sbs; + sbs.push_back(p_albedo_texture); + sbs.push_back(p_emission_texture); + sbs.push_back(p_emission_aniso_texture); + sbs.push_back(p_geom_facing_texture); + + //print_line("re-render " + p_from + " - " + p_size + " bounds " + p_bounds); + for (int i = 0; i < 3; i++) { + scene_state.ubo.sdf_offset[i] = p_from[i]; + scene_state.ubo.sdf_size[i] = p_size[i]; + } + + for (int i = 0; i < 3; i++) { + Vector3 axis; + axis[i] = 1.0; + Vector3 up, right; + int right_axis = (i + 1) % 3; + int up_axis = (i + 2) % 3; + up[up_axis] = 1.0; + right[right_axis] = 1.0; + + Size2i fb_size; + 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); + + //print_line("pass: " + itos(i) + " xform " + cam_xform); + + 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); + //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); + + store_transform(to_bounds.affine_inverse() * cam_xform, scene_state.ubo.sdf_to_bounds); + + _setup_environment(RID(), RID(), camera_proj, cam_xform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); + + Map<Size2i, RID>::Element *E = sdfgi_framebuffer_size_cache.find(fb_size); + if (!E) { + RID fb = RD::get_singleton()->framebuffer_create_empty(fb_size); + E = sdfgi_framebuffer_size_cache.insert(fb_size, fb); + } + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(E->get()), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), render_buffer->render_sdfgi_uniform_set, false); //second regular triangles + RD::get_singleton()->draw_list_end(); + } +} + void RasterizerSceneHighEndRD::_base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); @@ -2682,49 +2846,6 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { } { RD::Uniform u; - u.binding = 8; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.gi_probe_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 9; - u.type = RD::UNIFORM_TYPE_TEXTURE; - int slot_count = gi_probe_get_slots().size(); - if (gi_probe_is_anisotropic()) { - u.ids.resize(slot_count * 3); - } else { - u.ids.resize(slot_count); - } - - for (int i = 0; i < slot_count; i++) { - RID probe = gi_probe_get_slots()[i]; - - if (gi_probe_is_anisotropic()) { - if (probe.is_null()) { - RID empty_tex = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - u.ids.write[i * 3 + 0] = empty_tex; - u.ids.write[i * 3 + 1] = empty_tex; - u.ids.write[i * 3 + 2] = empty_tex; - } else { - u.ids.write[i * 3 + 0] = gi_probe_instance_get_texture(probe); - u.ids.write[i * 3 + 1] = gi_probe_instance_get_aniso_texture(probe, 0); - u.ids.write[i * 3 + 2] = gi_probe_instance_get_aniso_texture(probe, 1); - } - } else { - if (probe.is_null()) { - u.ids.write[i] = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - } else { - u.ids.write[i] = gi_probe_instance_get_texture(probe); - } - } - } - - uniforms.push_back(u); - } - { - RD::Uniform u; u.binding = 10; u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.ids.push_back(scene_state.lightmap_buffer); @@ -2803,11 +2924,19 @@ void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { uniforms.push_back(u); } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 20; + u.ids.push_back(sdfgi_get_ubo()); + uniforms.push_back(u); + } + render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET); } } -void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas) { +void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) { if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { RD::get_singleton()->free(view_dependant_uniform_set); } @@ -2844,6 +2973,25 @@ void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_at uniforms.push_back(u); } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID default_tex = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + for (int i = 0; i < MAX_GI_PROBES; i++) { + if (i < p_gi_probe_cull_count) { + RID tex = gi_probe_instance_get_texture(p_gi_probe_cull_result[i]); + if (!tex.is_valid()) { + tex = default_tex; + } + u.ids.push_back(tex); + } else { + u.ids.push_back(default_tex); + } + } + + uniforms.push_back(u); + } view_dependant_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, VIEW_DEPENDANT_UNIFORM_SET); } @@ -2860,16 +3008,22 @@ void RasterizerSceneHighEndRD::_render_buffers_uniform_set_changed(RID p_render_ _render_buffers_clear_uniform_set(rb); } -RID RasterizerSceneHighEndRD::_render_buffers_get_roughness_texture(RID p_render_buffers) { +RID RasterizerSceneHighEndRD::_render_buffers_get_normal_texture(RID p_render_buffers) { RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - return rb->roughness_buffer; + return rb->normal_roughness_buffer; } -RID RasterizerSceneHighEndRD::_render_buffers_get_normal_texture(RID p_render_buffers) { +RID RasterizerSceneHighEndRD::_render_buffers_get_ambient_texture(RID p_render_buffers) { RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - return rb->normal_buffer; + return rb->ambient_buffer; +} + +RID RasterizerSceneHighEndRD::_render_buffers_get_reflection_texture(RID p_render_buffers) { + RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + + return rb->reflection_buffer; } void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_buffers) { @@ -2898,30 +3052,70 @@ void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_b RD::Uniform u; u.binding = 2; u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb->normal_buffer.is_valid() ? rb->normal_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + RID texture = rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); u.ids.push_back(texture); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 3; + u.binding = 4; u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb->roughness_buffer.is_valid() ? rb->roughness_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID aot = render_buffers_get_ao_texture(p_render_buffers); + RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); } { RD::Uniform u; - u.binding = 4; + u.binding = 5; u.type = RD::UNIFORM_TYPE_TEXTURE; - RID aot = render_buffers_get_ao_texture(p_render_buffers); - RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + RID texture = rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); u.ids.push_back(texture); uniforms.push_back(u); } + { + RD::Uniform u; + u.binding = 6; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 7; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID t; + if (render_buffers_is_sdfgi_enabled(p_render_buffers)) { + t = render_buffers_get_sdfgi_irradiance_probes(p_render_buffers); + } else { + t = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + } + u.ids.push_back(t); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 8; + u.type = RD::UNIFORM_TYPE_TEXTURE; + if (render_buffers_is_sdfgi_enabled(p_render_buffers)) { + u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers)); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 9; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(render_buffers_get_gi_probe_buffer(p_render_buffers)); + uniforms.push_back(u); + } + rb->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); } } @@ -2946,6 +3140,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag if (is_using_radiance_cubemap_array()) { defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; } + defines += "\n#define SDFGI_OCT_SIZE " + itos(sdfgi_get_lightprobe_octahedron_size()) + "\n"; uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); @@ -2977,36 +3172,6 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(scene_state.max_directional_lights) + "\n"; } - - { //giprobes - int slot_count = gi_probe_get_slots().size(); - if (gi_probe_is_anisotropic()) { - slot_count *= 3; - defines += "\n#define GI_PROBE_USE_ANISOTROPY\n"; - } - - if (gi_probe_get_quality() == GIPROBE_QUALITY_ULTRA_LOW) { - defines += "\n#define GI_PROBE_LOW_QUALITY\n"; - } else if (gi_probe_get_quality() == GIPROBE_QUALITY_HIGH) { - defines += "\n#define GI_PROBE_HIGH_QUALITY\n"; - } - - defines += "\n#define MAX_GI_PROBE_TEXTURES " + itos(slot_count) + "\n"; - - uint32_t giprobe_buffer_size; - if (uniform_max_size < 65536) { - //Yes, you guessed right, ARM again - giprobe_buffer_size = uniform_max_size; - } else { - giprobe_buffer_size = 65536; - } - - giprobe_buffer_size = MIN(sizeof(GIProbeData) * gi_probe_get_slots().size(), giprobe_buffer_size); - scene_state.max_gi_probes = giprobe_buffer_size / sizeof(GIProbeData); - scene_state.gi_probes = memnew_arr(GIProbeData, scene_state.max_gi_probes); - scene_state.gi_probe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * scene_state.max_gi_probes); - defines += "\n#define MAX_GI_PROBES " + itos(scene_state.max_gi_probes) + "\n"; - } { //lightmaps scene_state.max_lightmaps = storage->lightmap_array_get_size(); @@ -3036,13 +3201,13 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag Vector<String> shader_versions; shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n#define MODE_RENDER_ROUGHNESS\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_GIPROBE\n"); shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); shader_versions.push_back(""); + shader_versions.push_back("\n#define USE_FORWARD_GI\n"); shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); - shader_versions.push_back("\n#define USE_VOXEL_CONE_TRACING\n"); - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_VOXEL_CONE_TRACING\n"); shader_versions.push_back("\n#define USE_LIGHTMAP\n"); shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); shader.scene_shader.initialize(shader_versions, defines); @@ -3109,7 +3274,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.renames["SCREEN_UV"] = "screen_uv"; actions.renames["SCREEN_TEXTURE"] = "color_buffer"; actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions.renames["NORMAL_TEXTURE"] = "normal_buffer"; + actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer"; actions.renames["DEPTH"] = "gl_FragDepth"; actions.renames["OUTPUT_IS_SRGB"] = "true"; @@ -3219,6 +3384,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); + default_shader_sdfgi_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); } { @@ -3268,7 +3434,7 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag { //render buffers Vector<RD::Uniform> uniforms; - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 7; i++) { RD::Uniform u; u.binding = i; u.type = RD::UNIFORM_TYPE_TEXTURE; @@ -3276,6 +3442,28 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag u.ids.push_back(texture); uniforms.push_back(u); } + { + RD::Uniform u; + u.binding = 7; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 8; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 9; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(render_buffers_get_default_gi_probe_buffer()); + uniforms.push_back(u); + } default_render_buffers_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); } @@ -3307,7 +3495,6 @@ RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { { RD::get_singleton()->free(scene_state.uniform_buffer); RD::get_singleton()->free(scene_state.instance_buffer); - RD::get_singleton()->free(scene_state.gi_probe_buffer); RD::get_singleton()->free(scene_state.directional_light_buffer); RD::get_singleton()->free(scene_state.light_buffer); RD::get_singleton()->free(scene_state.lightmap_buffer); @@ -3315,7 +3502,6 @@ RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { RD::get_singleton()->free(scene_state.reflection_buffer); RD::get_singleton()->free(scene_state.decal_buffer); memdelete_arr(scene_state.instances); - memdelete_arr(scene_state.gi_probes); memdelete_arr(scene_state.directional_lights); memdelete_arr(scene_state.lights); memdelete_arr(scene_state.lightmaps); @@ -3323,4 +3509,9 @@ RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { memdelete_arr(scene_state.reflections); memdelete_arr(scene_state.decals); } + + while (sdfgi_framebuffer_size_cache.front()) { + RD::get_singleton()->free(sdfgi_framebuffer_size_cache.front()->get()); + sdfgi_framebuffer_size_cache.erase(sdfgi_framebuffer_size_cache.front()); + } } diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h index 8438a4f730..cb03da48c1 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -47,18 +47,23 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { MATERIAL_UNIFORM_SET = 5 }; + enum { + SDFGI_MAX_CASCADES = 8, + MAX_GI_PROBES = 8 + }; + /* Scene Shader */ enum ShaderVersion { SHADER_VERSION_DEPTH_PASS, SHADER_VERSION_DEPTH_PASS_DP, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL, SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, + SHADER_VERSION_DEPTH_PASS_WITH_SDF, SHADER_VERSION_COLOR_PASS, + SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_VCT_COLOR_PASS, - SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR, SHADER_VERSION_LIGHTMAP_COLOR_PASS, SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, SHADER_VERSION_MAX @@ -203,8 +208,11 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { RID color; RID depth; RID specular; - RID normal_buffer; - RID roughness_buffer; + RID normal_roughness_buffer; + RID giprobe_buffer; + + RID ambient_buffer; + RID reflection_buffer; RS::ViewportMSAA msaa; RD::TextureSamples texture_samples; @@ -212,18 +220,22 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { RID color_msaa; RID depth_msaa; RID specular_msaa; - RID normal_buffer_msaa; + RID normal_roughness_buffer_msaa; RID roughness_buffer_msaa; + RID giprobe_buffer_msaa; RID depth_fb; - RID depth_normal_fb; RID depth_normal_roughness_fb; + RID depth_normal_roughness_giprobe_fb; RID color_fb; RID color_specular_fb; RID specular_only_fb; int width, height; + RID render_sdfgi_uniform_set; void ensure_specular(); + void ensure_gi(); + void ensure_giprobe(); void clear(); virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa); @@ -233,8 +245,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { }; virtual RenderBufferData *_create_render_buffer_data(); - void _allocate_normal_texture(RenderBufferDataHighEnd *rb); - void _allocate_roughness_texture(RenderBufferDataHighEnd *rb); + void _allocate_normal_roughness_texture(RenderBufferDataHighEnd *rb); RID shadow_sampler; RID render_base_uniform_set; @@ -245,11 +256,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { virtual void _base_uniforms_changed(); void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb); virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); - virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers); virtual RID _render_buffers_get_normal_texture(RID p_render_buffers); + virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers); + virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers); void _update_render_base_uniform_set(); - void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas); + void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count); void _update_render_buffers_uniform_set(RID p_render_buffers); /* Scene State UBO */ @@ -260,7 +272,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float box_offset[3]; uint32_t mask; float params[4]; // intensity, 0, interior , boxproject - float ambient[4]; // ambient color, energy + float ambient[3]; // ambient color, + uint32_t ambient_mode; float local_matrix[16]; // up to here for spot and omni, rest is for directional }; @@ -315,22 +328,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float uv_scale4[2]; }; - struct GIProbeData { - float xform[16]; - float bounds[3]; - float dynamic_range; - - float bias; - float normal_bias; - uint32_t blend_ambient; - uint32_t texture_slot; - - float anisotropy_strength; - float ao; - float ao_size; - uint32_t pad[1]; - }; - struct LightmapData { float normal_xform[12]; }; @@ -358,6 +355,8 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { }; enum { + INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6, + INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7, INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, @@ -430,10 +429,19 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float ssao_ao_affect; uint32_t roughness_limiter_enabled; + float roughness_limiter_amount; + float roughness_limiter_limit; + uint32_t roughness_limiter_pad[2]; + float ao_color[4]; + float sdf_to_bounds[16]; + + int32_t sdf_offset[3]; uint32_t material_uv2_mode; - uint32_t pad_material[3]; + + int32_t sdf_size[3]; + uint32_t gi_upscale_for_msaa; }; UBO ubo; @@ -445,11 +453,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { RID reflection_buffer; uint32_t max_reflection_probes_per_instance; - GIProbeData *gi_probes; - uint32_t max_gi_probes; - RID gi_probe_buffer; - uint32_t max_gi_probe_probes_per_instance; - LightmapData *lightmaps; uint32_t max_lightmaps; RID lightmap_buffer; @@ -498,7 +501,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { uint64_t material_index : 15; uint64_t shader_index : 12; uint64_t uses_instancing : 1; - uint64_t uses_vct : 1; + uint64_t uses_forward_gi : 1; uint64_t uses_lightmap : 1; uint64_t depth_layer : 4; uint64_t priority : 8; @@ -625,6 +628,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { RID wireframe_material_shader; RID wireframe_material; RID default_shader_rd; + RID default_shader_sdfgi_rd; RID default_radiance_uniform_set; RID default_render_buffers_uniform_set; @@ -640,30 +644,33 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { PASS_MODE_SHADOW, PASS_MODE_SHADOW_DP, PASS_MODE_DEPTH, - PASS_MODE_DEPTH_NORMAL, PASS_MODE_DEPTH_NORMAL_ROUGHNESS, + PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE, PASS_MODE_DEPTH_MATERIAL, + PASS_MODE_SDF, }; - void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_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); + 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 Size2 &p_screen_pixel_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); void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows); void _setup_decals(const RID *p_decal_instances, int p_decal_count, const Transform &p_camera_inverse_xform); void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment); - void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform); void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, const Transform &p_cam_transform); - void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth); + void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false); void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2()); - _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index); - _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index); + _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false); + _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false); + + void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_using_sdfgi = false); - void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi); + Map<Size2i, RID> sdfgi_framebuffer_size_cache; protected: virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, 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); virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, 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); virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); + virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture); public: virtual void set_time(double p_time, double p_step); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index 689552be2f..dd68011111 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -32,6 +32,7 @@ #include "core/os/os.h" #include "core/project_settings.h" +#include "rasterizer_rd.h" #include "servers/rendering/rendering_server_raster.h" uint64_t RasterizerSceneRD::auto_exposure_counter = 2; @@ -195,6 +196,1541 @@ void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd) { } } +void RasterizerSceneRD::_sdfgi_erase(RenderBuffers *rb) { + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + const SDFGI::Cascade &c = rb->sdfgi->cascades[i]; + RD::get_singleton()->free(c.light_data); + RD::get_singleton()->free(c.light_aniso_0_tex); + RD::get_singleton()->free(c.light_aniso_1_tex); + RD::get_singleton()->free(c.sdf_tex); + RD::get_singleton()->free(c.solid_cell_dispatch_buffer); + RD::get_singleton()->free(c.solid_cell_buffer); + RD::get_singleton()->free(c.lightprobe_history_tex); + RD::get_singleton()->free(c.lightprobe_average_tex); + RD::get_singleton()->free(c.lights_buffer); + } + + RD::get_singleton()->free(rb->sdfgi->render_albedo); + RD::get_singleton()->free(rb->sdfgi->render_emission); + RD::get_singleton()->free(rb->sdfgi->render_emission_aniso); + + RD::get_singleton()->free(rb->sdfgi->render_sdf[0]); + RD::get_singleton()->free(rb->sdfgi->render_sdf[1]); + + RD::get_singleton()->free(rb->sdfgi->render_sdf_half[0]); + RD::get_singleton()->free(rb->sdfgi->render_sdf_half[1]); + + for (int i = 0; i < 8; i++) { + RD::get_singleton()->free(rb->sdfgi->render_occlusion[i]); + } + + RD::get_singleton()->free(rb->sdfgi->render_geom_facing); + + RD::get_singleton()->free(rb->sdfgi->lightprobe_data); + RD::get_singleton()->free(rb->sdfgi->lightprobe_history_scroll); + RD::get_singleton()->free(rb->sdfgi->occlusion_data); + + RD::get_singleton()->free(rb->sdfgi->cascades_ubo); + + memdelete(rb->sdfgi); + + rb->sdfgi = nullptr; +} + +const Vector3i RasterizerSceneRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF); + +void RasterizerSceneRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) { + Environent *env = environment_owner.getornull(p_environment); + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + bool needs_sdfgi = env && env->sdfgi_enabled; + + if (!needs_sdfgi) { + if (rb->sdfgi != nullptr) { + //erase it + _sdfgi_erase(rb); + _render_buffers_uniform_set_changed(p_render_buffers); + } + return; + } + + static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 }; + uint32_t requested_history_size = history_frames_to_converge[sdfgi_frames_to_converge]; + + if (rb->sdfgi && (rb->sdfgi->cascade_mode != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) { + //configuration changed, erase + _sdfgi_erase(rb); + } + + SDFGI *sdfgi = rb->sdfgi; + if (sdfgi == nullptr) { + //re-create + rb->sdfgi = memnew(SDFGI); + sdfgi = rb->sdfgi; + sdfgi->cascade_mode = env->sdfgi_cascades; + sdfgi->min_cell_size = env->sdfgi_min_cell_size; + sdfgi->uses_occlusion = env->sdfgi_use_occlusion; + sdfgi->y_scale_mode = env->sdfgi_y_scale; + static const float y_scale[3] = { 1.0, 1.5, 2.0 }; + sdfgi->y_mult = y_scale[sdfgi->y_scale_mode]; + static const int cascasde_size[3] = { 4, 6, 8 }; + sdfgi->cascades.resize(cascasde_size[sdfgi->cascade_mode]); + sdfgi->probe_axis_count = SDFGI::PROBE_DIVISOR + 1; + sdfgi->solid_cell_ratio = sdfgi_solid_cell_ratio; + sdfgi->solid_cell_count = uint32_t(float(sdfgi->cascade_size * sdfgi->cascade_size * sdfgi->cascade_size) * sdfgi->solid_cell_ratio); + + float base_cell_size = sdfgi->min_cell_size; + + RD::TextureFormat tf_sdf; + tf_sdf.format = RD::DATA_FORMAT_R8_UNORM; + tf_sdf.width = sdfgi->cascade_size; // Always 64x64 + tf_sdf.height = sdfgi->cascade_size; + tf_sdf.depth = sdfgi->cascade_size; + tf_sdf.type = RD::TEXTURE_TYPE_3D; + tf_sdf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + + { + RD::TextureFormat tf_render = tf_sdf; + tf_render.format = RD::DATA_FORMAT_R16_UINT; + sdfgi->render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + tf_render.format = RD::DATA_FORMAT_R32_UINT; + sdfgi->render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + sdfgi->render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + + tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize + + for (int i = 0; i < 8; i++) { + sdfgi->render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + } + + tf_render.format = RD::DATA_FORMAT_R32_UINT; + sdfgi->render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + + tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT; + sdfgi->render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + sdfgi->render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + + tf_render.width /= 2; + tf_render.height /= 2; + tf_render.depth /= 2; + + sdfgi->render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + sdfgi->render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + } + + RD::TextureFormat tf_occlusion = tf_sdf; + tf_occlusion.format = RD::DATA_FORMAT_R16_UINT; + tf_occlusion.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT); + tf_occlusion.shareable_formats.push_back(RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16); + tf_occlusion.depth *= sdfgi->cascades.size(); //use depth for occlusion slices + tf_occlusion.width *= 2; //use width for the other half + + RD::TextureFormat tf_light = tf_sdf; + tf_light.format = RD::DATA_FORMAT_R32_UINT; + tf_light.shareable_formats.push_back(RD::DATA_FORMAT_R32_UINT); + tf_light.shareable_formats.push_back(RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32); + + RD::TextureFormat tf_aniso0 = tf_sdf; + tf_aniso0.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + RD::TextureFormat tf_aniso1 = tf_sdf; + tf_aniso1.format = RD::DATA_FORMAT_R8G8_UNORM; + + int passes = nearest_shift(sdfgi->cascade_size) - 1; + + //store lightprobe SH + RD::TextureFormat tf_probes; + tf_probes.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf_probes.width = sdfgi->probe_axis_count * sdfgi->probe_axis_count; + tf_probes.height = sdfgi->probe_axis_count * SDFGI::SH_SIZE; + tf_probes.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + tf_probes.type = RD::TEXTURE_TYPE_2D_ARRAY; + + sdfgi->history_size = requested_history_size; + + RD::TextureFormat tf_probe_history = tf_probes; + tf_probe_history.format = RD::DATA_FORMAT_R16G16B16A16_SINT; //signed integer because SH are signed + tf_probe_history.array_layers = sdfgi->history_size; + + RD::TextureFormat tf_probe_average = tf_probes; + tf_probe_average.format = RD::DATA_FORMAT_R32G32B32A32_SINT; //signed integer because SH are signed + tf_probe_average.type = RD::TEXTURE_TYPE_2D_ARRAY; + tf_probe_average.array_layers = 1; + + sdfgi->lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + sdfgi->lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + + { + //octahedral lightprobes + RD::TextureFormat tf_octprobes = tf_probes; + tf_octprobes.array_layers = sdfgi->cascades.size() * 2; + tf_octprobes.format = RD::DATA_FORMAT_R32_UINT; //pack well with RGBE + tf_octprobes.width = sdfgi->probe_axis_count * sdfgi->probe_axis_count * (SDFGI::LIGHTPROBE_OCT_SIZE + 2); + tf_octprobes.height = sdfgi->probe_axis_count * (SDFGI::LIGHTPROBE_OCT_SIZE + 2); + tf_octprobes.shareable_formats.push_back(RD::DATA_FORMAT_R32_UINT); + tf_octprobes.shareable_formats.push_back(RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32); + //lightprobe texture is an octahedral texture + + sdfgi->lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView()); + RD::TextureView tv; + tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; + sdfgi->lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, sdfgi->lightprobe_data); + } + + sdfgi->cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES); + + sdfgi->occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView()); + { + RD::TextureView tv; + tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16; + sdfgi->occlusion_texture = RD::get_singleton()->texture_create_shared(tv, sdfgi->occlusion_data); + } + + for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { + SDFGI::Cascade &cascade = sdfgi->cascades[i]; + + /* 3D Textures */ + + cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView()); + + cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView()); + + cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView()); + cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView()); + + { + RD::TextureView tv; + tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; + cascade.light_tex = RD::get_singleton()->texture_create_shared(tv, cascade.light_data); + + RD::get_singleton()->texture_clear(cascade.light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); + RD::get_singleton()->texture_clear(cascade.light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); + RD::get_singleton()->texture_clear(cascade.light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); + } + + cascade.cell_size = base_cell_size; + Vector3 world_position = p_world_position; + world_position.y *= sdfgi->y_mult; + int32_t probe_cells = sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; + Vector3 probe_size = Vector3(1, 1, 1) * cascade.cell_size * probe_cells; + Vector3i probe_pos = Vector3i((world_position / probe_size + Vector3(0.5, 0.5, 0.5)).floor()); + cascade.position = probe_pos * probe_cells; + + cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL; + + base_cell_size *= 2.0; + + /* Probe History */ + + cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work + + cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work + + /* Buffers */ + + cascade.solid_cell_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDFGI::Cascade::SolidCell) * sdfgi->solid_cell_count); + cascade.solid_cell_dispatch_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 4, Vector<uint8_t>(), RD::STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT); + cascade.lights_buffer = RD::get_singleton()->storage_buffer_create(sizeof(SDGIShader::Light) * MAX(SDFGI::MAX_STATIC_LIGHTS, SDFGI::MAX_DYNAMIC_LIGHTS)); + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_sdf[(passes & 1) ? 1 : 0]); //if passes are even, we read from buffer 0, else we read from buffer 1 + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->render_albedo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + for (int j = 0; j < 8; j++) { + u.ids.push_back(sdfgi->render_occlusion[j]); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 4; + u.ids.push_back(sdfgi->render_emission); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(sdfgi->render_emission_aniso); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 6; + u.ids.push_back(sdfgi->render_geom_facing); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 7; + u.ids.push_back(cascade.sdf_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 8; + u.ids.push_back(sdfgi->occlusion_data); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 10; + u.ids.push_back(cascade.solid_cell_dispatch_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 11; + u.ids.push_back(cascade.solid_cell_buffer); + uniforms.push_back(u); + } + + cascade.sdf_store_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_STORE), 0); + } + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_albedo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->render_geom_facing); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.ids.push_back(sdfgi->render_emission); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 4; + u.ids.push_back(sdfgi->render_emission_aniso); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 5; + u.ids.push_back(cascade.solid_cell_dispatch_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 6; + u.ids.push_back(cascade.solid_cell_buffer); + uniforms.push_back(u); + } + + cascade.scroll_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_SCROLL), 0); + } + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + for (int j = 0; j < 8; j++) { + u.ids.push_back(sdfgi->render_occlusion[j]); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->occlusion_data); + uniforms.push_back(u); + } + + cascade.scroll_occlusion_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_SCROLL_OCCLUSION), 0); + } + } + + //direct light + for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { + SDFGI::Cascade &cascade = sdfgi->cascades[i]; + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (j < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(cascade.solid_cell_dispatch_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(cascade.solid_cell_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 5; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.ids.push_back(cascade.light_data); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 6; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.ids.push_back(cascade.light_aniso_0_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 7; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.ids.push_back(cascade.light_aniso_1_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 8; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(rb->sdfgi->cascades_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 9; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(cascade.lights_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 10; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(rb->sdfgi->lightprobe_texture); + uniforms.push_back(u); + } + + cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, 0), 0); + } + + //preprocess initialize uniform set + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_albedo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->render_sdf[0]); + uniforms.push_back(u); + } + + sdfgi->sdf_initialize_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE), 0); + } + + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_albedo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->render_sdf_half[0]); + uniforms.push_back(u); + } + + sdfgi->sdf_initialize_half_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF), 0); + } + + //jump flood uniform set + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_sdf[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->render_sdf[1]); + uniforms.push_back(u); + } + + sdfgi->jump_flood_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0); + SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]); + sdfgi->jump_flood_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0); + } + //jump flood half uniform set + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_sdf_half[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->render_sdf_half[1]); + uniforms.push_back(u); + } + + sdfgi->jump_flood_half_uniform_set[0] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0); + SWAP(uniforms.write[0].ids.write[0], uniforms.write[1].ids.write[0]); + sdfgi->jump_flood_half_uniform_set[1] = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD), 0); + } + + //upscale half size sdf + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_albedo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + u.ids.push_back(sdfgi->render_sdf_half[(passes & 1) ? 0 : 1]); //reverse pass order because half size + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.ids.push_back(sdfgi->render_sdf[(passes & 1) ? 0 : 1]); //reverse pass order because it needs an extra JFA pass + uniforms.push_back(u); + } + + sdfgi->upscale_jfa_uniform_set_index = (passes & 1) ? 0 : 1; + sdfgi->sdf_upscale_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE), 0); + } + + //occlusion uniform set + { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 1; + u.ids.push_back(sdfgi->render_albedo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 2; + for (int i = 0; i < 8; i++) { + u.ids.push_back(sdfgi->render_occlusion[i]); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.ids.push_back(sdfgi->render_geom_facing); + uniforms.push_back(u); + } + + sdfgi->occlusion_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, SDGIShader::PRE_PROCESS_OCCLUSION), 0); + } + + for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { + //integrate uniform + + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (j < sdfgi->cascades.size()) { + u.ids.push_back(sdfgi->cascades[j].sdf_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (j < sdfgi->cascades.size()) { + u.ids.push_back(sdfgi->cascades[j].light_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (j < sdfgi->cascades.size()) { + u.ids.push_back(sdfgi->cascades[j].light_aniso_0_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (j < sdfgi->cascades.size()) { + u.ids.push_back(sdfgi->cascades[j].light_aniso_1_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 6; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 7; + u.ids.push_back(sdfgi->cascades_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 8; + u.ids.push_back(sdfgi->lightprobe_data); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 9; + u.ids.push_back(sdfgi->cascades[i].lightprobe_history_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 10; + u.ids.push_back(sdfgi->cascades[i].lightprobe_average_tex); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 11; + u.ids.push_back(sdfgi->lightprobe_history_scroll); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 12; + u.ids.push_back(sdfgi->lightprobe_average_scroll); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 13; + RID parent_average; + if (i < sdfgi->cascades.size() - 1) { + parent_average = sdfgi->cascades[i + 1].lightprobe_average_tex; + } else { + parent_average = sdfgi->cascades[i - 1].lightprobe_average_tex; //to use something, but it wont be used + } + u.ids.push_back(parent_average); + uniforms.push_back(u); + } + + sdfgi->cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 0); + } + + sdfgi->uses_multibounce = env->sdfgi_use_multibounce; + sdfgi->energy = env->sdfgi_energy; + sdfgi->normal_bias = env->sdfgi_normal_bias; + sdfgi->probe_bias = env->sdfgi_probe_bias; + sdfgi->reads_sky = env->sdfgi_read_sky_light; + + _render_buffers_uniform_set_changed(p_render_buffers); + + return; //done. all levels will need to be rendered which its going to take a bit + } + + //check for updates + + sdfgi->uses_multibounce = env->sdfgi_use_multibounce; + sdfgi->energy = env->sdfgi_energy; + sdfgi->normal_bias = env->sdfgi_normal_bias; + sdfgi->probe_bias = env->sdfgi_probe_bias; + sdfgi->reads_sky = env->sdfgi_read_sky_light; + + int32_t drag_margin = (sdfgi->cascade_size / SDFGI::PROBE_DIVISOR) / 2; + + for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) { + SDFGI::Cascade &cascade = sdfgi->cascades[i]; + cascade.dirty_regions = Vector3i(); + + Vector3 probe_half_size = Vector3(1, 1, 1) * cascade.cell_size * float(sdfgi->cascade_size / SDFGI::PROBE_DIVISOR) * 0.5; + probe_half_size = Vector3(0, 0, 0); + + Vector3 world_position = p_world_position; + world_position.y *= sdfgi->y_mult; + Vector3i pos_in_cascade = Vector3i((world_position + probe_half_size) / cascade.cell_size); + + for (int j = 0; j < 3; j++) { + if (pos_in_cascade[j] < cascade.position[j]) { + while (pos_in_cascade[j] < (cascade.position[j] - drag_margin)) { + cascade.position[j] -= drag_margin * 2; + cascade.dirty_regions[j] += drag_margin * 2; + } + } else if (pos_in_cascade[j] > cascade.position[j]) { + while (pos_in_cascade[j] > (cascade.position[j] + drag_margin)) { + cascade.position[j] += drag_margin * 2; + cascade.dirty_regions[j] -= drag_margin * 2; + } + } + + if (cascade.dirty_regions[j] == 0) { + continue; // not dirty + } else if (uint32_t(ABS(cascade.dirty_regions[j])) >= sdfgi->cascade_size) { + //moved too much, just redraw everything (make all dirty) + cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL; + break; + } + } + + if (cascade.dirty_regions != Vector3i() && cascade.dirty_regions != SDFGI::Cascade::DIRTY_ALL) { + //see how much the total dirty volume represents from the total volume + uint32_t total_volume = sdfgi->cascade_size * sdfgi->cascade_size * sdfgi->cascade_size; + uint32_t safe_volume = 1; + for (int j = 0; j < 3; j++) { + safe_volume *= sdfgi->cascade_size - ABS(cascade.dirty_regions[j]); + } + uint32_t dirty_volume = total_volume - safe_volume; + if (dirty_volume > (safe_volume / 2)) { + //more than half the volume is dirty, make all dirty so its only rendered once + cascade.dirty_regions = SDFGI::Cascade::DIRTY_ALL; + } + } + } +} + +int RasterizerSceneRD::sdfgi_get_pending_region_count(RID p_render_buffers) const { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + + ERR_FAIL_COND_V(rb == nullptr, 0); + + if (rb->sdfgi == nullptr) { + return 0; + } + + int dirty_count = 0; + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + const SDFGI::Cascade &c = rb->sdfgi->cascades[i]; + + if (c.dirty_regions == SDFGI::Cascade::DIRTY_ALL) { + dirty_count++; + } else { + for (int j = 0; j < 3; j++) { + if (c.dirty_regions[j] != 0) { + dirty_count++; + } + } + } + } + + return dirty_count; +} + +int RasterizerSceneRD::_sdfgi_get_pending_region_data(RID p_render_buffers, int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(rb == nullptr, -1); + ERR_FAIL_COND_V(rb->sdfgi == nullptr, -1); + + int dirty_count = 0; + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + const SDFGI::Cascade &c = rb->sdfgi->cascades[i]; + + if (c.dirty_regions == SDFGI::Cascade::DIRTY_ALL) { + if (dirty_count == p_region) { + r_local_offset = Vector3i(); + r_local_size = Vector3i(1, 1, 1) * rb->sdfgi->cascade_size; + + r_bounds.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + c.position)) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1); + r_bounds.size = Vector3(r_local_size) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1); + return i; + } + dirty_count++; + } else { + for (int j = 0; j < 3; j++) { + if (c.dirty_regions[j] != 0) { + if (dirty_count == p_region) { + Vector3i from = Vector3i(0, 0, 0); + Vector3i to = Vector3i(1, 1, 1) * rb->sdfgi->cascade_size; + + if (c.dirty_regions[j] > 0) { + //fill from the beginning + to[j] = c.dirty_regions[j]; + } else { + //fill from the end + from[j] = to[j] + c.dirty_regions[j]; + } + + for (int k = 0; k < j; k++) { + // "chip" away previous regions to avoid re-voxelizing the same thing + if (c.dirty_regions[k] > 0) { + from[k] += c.dirty_regions[k]; + } else if (c.dirty_regions[k] < 0) { + to[k] += c.dirty_regions[k]; + } + } + + r_local_offset = from; + r_local_size = to - from; + + r_bounds.position = Vector3(from + Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + c.position) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1); + r_bounds.size = Vector3(r_local_size) * c.cell_size * Vector3(1, 1.0 / rb->sdfgi->y_mult, 1); + + return i; + } + + dirty_count++; + } + } + } + } + return -1; +} + +AABB RasterizerSceneRD::sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const { + AABB bounds; + Vector3i from; + Vector3i size; + + int c = _sdfgi_get_pending_region_data(p_render_buffers, p_region, from, size, bounds); + ERR_FAIL_COND_V(c == -1, AABB()); + return bounds; +} + +uint32_t RasterizerSceneRD::sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const { + AABB bounds; + Vector3i from; + Vector3i size; + + return _sdfgi_get_pending_region_data(p_render_buffers, p_region, from, size, bounds); +} + +void RasterizerSceneRD::_sdfgi_update_cascades(RID p_render_buffers) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(rb == nullptr); + if (rb->sdfgi == nullptr) { + return; + } + + //update cascades + SDFGI::Cascade::UBO cascade_data[SDFGI::MAX_CASCADES]; + int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; + + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + Vector3 pos = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[i].position)) * rb->sdfgi->cascades[i].cell_size; + + cascade_data[i].offset[0] = pos.x; + cascade_data[i].offset[1] = pos.y; + cascade_data[i].offset[2] = pos.z; + cascade_data[i].to_cell = 1.0 / rb->sdfgi->cascades[i].cell_size; + cascade_data[i].probe_offset[0] = rb->sdfgi->cascades[i].position.x / probe_divisor; + cascade_data[i].probe_offset[1] = rb->sdfgi->cascades[i].position.y / probe_divisor; + cascade_data[i].probe_offset[2] = rb->sdfgi->cascades[i].position.z / probe_divisor; + cascade_data[i].pad = 0; + } + + RD::get_singleton()->buffer_update(rb->sdfgi->cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, true); +} + +void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(rb == nullptr); + if (rb->sdfgi == nullptr) { + return; + } + Environent *env = environment_owner.getornull(p_environment); + + RENDER_TIMESTAMP(">SDFGI Update Probes"); + + /* Update Cascades UBO */ + _sdfgi_update_cascades(p_render_buffers); + /* Update Dynamic Lights Buffer */ + + RENDER_TIMESTAMP("Update Lights"); + + /* Update dynamic lights */ + + { + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.direct_light_pipeline[SDGIShader::DIRECT_LIGHT_MODE_DYNAMIC]); + + SDGIShader::DirectLightPushConstant push_constant; + + push_constant.grid_size[0] = rb->sdfgi->cascade_size; + push_constant.grid_size[1] = rb->sdfgi->cascade_size; + push_constant.grid_size[2] = rb->sdfgi->cascade_size; + push_constant.max_cascades = rb->sdfgi->cascades.size(); + push_constant.probe_axis_size = rb->sdfgi->probe_axis_count; + push_constant.multibounce = rb->sdfgi->uses_multibounce; + push_constant.y_mult = rb->sdfgi->y_mult; + + push_constant.process_offset = 0; + push_constant.process_increment = 1; + + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + SDFGI::Cascade &cascade = rb->sdfgi->cascades[i]; + + { //fill light buffer + + SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS]; + uint32_t idx = 0; + for (uint32_t j = 0; j < p_directional_light_count; j++) { + if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { + break; + } + + LightInstance *li = light_instance_owner.getornull(p_directional_light_instances[j]); + ERR_CONTINUE(!li); + Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); + dir.y *= rb->sdfgi->y_mult; + dir.normalize(); + lights[idx].direction[0] = dir.x; + lights[idx].direction[1] = dir.y; + lights[idx].direction[2] = dir.z; + Color color = storage->light_get_color(li->light); + color = color.to_linear(); + lights[idx].color[0] = color.r; + lights[idx].color[1] = color.g; + lights[idx].color[2] = color.b; + lights[idx].type = RS::LIGHT_DIRECTIONAL; + lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].has_shadow = storage->light_has_shadow(li->light); + + idx++; + } + + AABB cascade_aabb; + cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + cascade.position)) * cascade.cell_size; + cascade_aabb.size = Vector3(1, 1, 1) * rb->sdfgi->cascade_size * cascade.cell_size; + + for (uint32_t j = 0; j < p_positional_light_count; j++) { + if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { + break; + } + + LightInstance *li = light_instance_owner.getornull(p_positional_light_instances[j]); + ERR_CONTINUE(!li); + + uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light); + if (i > max_sdfgi_cascade) { + continue; + } + + if (!cascade_aabb.intersects(li->aabb)) { + continue; + } + + Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); + //faster to not do this here + //dir.y *= rb->sdfgi->y_mult; + //dir.normalize(); + lights[idx].direction[0] = dir.x; + lights[idx].direction[1] = dir.y; + lights[idx].direction[2] = dir.z; + Vector3 pos = li->transform.origin; + pos.y *= rb->sdfgi->y_mult; + lights[idx].position[0] = pos.x; + lights[idx].position[1] = pos.y; + lights[idx].position[2] = pos.z; + Color color = storage->light_get_color(li->light); + color = color.to_linear(); + lights[idx].color[0] = color.r; + lights[idx].color[1] = color.g; + lights[idx].color[2] = color.b; + lights[idx].type = storage->light_get_type(li->light); + lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].has_shadow = storage->light_has_shadow(li->light); + lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); + lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); + lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)); + lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + idx++; + } + + if (idx > 0) { + RD::get_singleton()->buffer_update(cascade.lights_buffer, 0, idx * sizeof(SDGIShader::Light), lights, true); + } + push_constant.light_count = idx; + } + + push_constant.cascade = i; + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::DirectLightPushConstant)); + RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0); + } + RD::get_singleton()->compute_list_end(); + } + + RENDER_TIMESTAMP("Raytrace"); + + SDGIShader::IntegratePushConstant push_constant; + push_constant.grid_size[1] = rb->sdfgi->cascade_size; + push_constant.grid_size[2] = rb->sdfgi->cascade_size; + push_constant.grid_size[0] = rb->sdfgi->cascade_size; + push_constant.max_cascades = rb->sdfgi->cascades.size(); + push_constant.probe_axis_size = rb->sdfgi->probe_axis_count; + push_constant.history_index = rb->sdfgi->render_pass % rb->sdfgi->history_size; + push_constant.history_size = rb->sdfgi->history_size; + static const uint32_t ray_count[RS::ENV_SDFGI_RAY_COUNT_MAX] = { 8, 16, 32, 64, 96, 128 }; + push_constant.ray_count = ray_count[sdfgi_ray_count]; + push_constant.ray_bias = rb->sdfgi->probe_bias; + push_constant.image_size[0] = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count; + push_constant.image_size[1] = rb->sdfgi->probe_axis_count; + + RID sky_uniform_set = sdfgi_shader.integrate_default_sky_uniform_set; + push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_DISABLED; + push_constant.y_mult = rb->sdfgi->y_mult; + + if (rb->sdfgi->reads_sky && env) { + push_constant.sky_energy = env->bg_energy; + + if (env->background == RS::ENV_BG_CLEAR_COLOR) { + push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_COLOR; + Color c = storage->get_default_clear_color().to_linear(); + push_constant.sky_color[0] = c.r; + push_constant.sky_color[1] = c.g; + push_constant.sky_color[2] = c.b; + } else if (env->background == RS::ENV_BG_COLOR) { + push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_COLOR; + Color c = env->bg_color; + push_constant.sky_color[0] = c.r; + push_constant.sky_color[1] = c.g; + push_constant.sky_color[2] = c.b; + + } else if (env->background == RS::ENV_BG_SKY) { + Sky *sky = sky_owner.getornull(env->sky); + if (sky && sky->radiance.is_valid()) { + if (sky->sdfgi_integrate_sky_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(sky->sdfgi_integrate_sky_uniform_set)) { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(sky->radiance); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 1; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + sky->sdfgi_integrate_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1); + } + sky_uniform_set = sky->sdfgi_integrate_sky_uniform_set; + push_constant.sky_mode = SDGIShader::IntegratePushConstant::SKY_MODE_SKY; + } + } + } + + rb->sdfgi->render_pass++; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_PROCESS]); + + int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + push_constant.cascade = i; + push_constant.world_offset[0] = rb->sdfgi->cascades[i].position.x / probe_divisor; + push_constant.world_offset[1] = rb->sdfgi->cascades[i].position.y / probe_divisor; + push_constant.world_offset[2] = rb->sdfgi->cascades[i].position.z / probe_divisor; + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[i].integrate_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sky_uniform_set, 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::IntegratePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count, rb->sdfgi->probe_axis_count, 1, 8, 8, 1); + } + + RD::get_singleton()->compute_list_add_barrier(compute_list); //wait until done + + // Then store values into the lightprobe texture. Separating these steps has a small performance hit, but it allows for multiple bounces + RENDER_TIMESTAMP("Average Probes"); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_STORE]); + + //convert to octahedral to store + push_constant.image_size[0] *= SDFGI::LIGHTPROBE_OCT_SIZE; + push_constant.image_size[1] *= SDFGI::LIGHTPROBE_OCT_SIZE; + + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + push_constant.cascade = i; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[i].integrate_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::IntegratePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, rb->sdfgi->probe_axis_count * SDFGI::LIGHTPROBE_OCT_SIZE, 1, 8, 8, 1); + } + + RD::get_singleton()->compute_list_end(); + + RENDER_TIMESTAMP("<SDFGI Update Probes"); +} + +void RasterizerSceneRD::_process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) { + RENDER_TIMESTAMP("Render GI"); + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(rb == nullptr); + Environent *env = environment_owner.getornull(p_environment); + + GI::PushConstant push_constant; + + push_constant.screen_size[0] = rb->width; + push_constant.screen_size[1] = rb->height; + push_constant.z_near = p_projection.get_z_near(); + push_constant.z_far = p_projection.get_z_far(); + push_constant.orthogonal = p_projection.is_orthogonal(); + push_constant.proj_info[0] = -2.0f / (rb->width * p_projection.matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (rb->height * p_projection.matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; + push_constant.max_giprobes = MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count); + push_constant.high_quality_vct = gi_probe_quality == RS::GI_PROBE_QUALITY_HIGH; + push_constant.use_sdfgi = rb->sdfgi != nullptr; + + if (env) { + push_constant.ao_color[0] = env->ao_color.r; + push_constant.ao_color[1] = env->ao_color.g; + push_constant.ao_color[2] = env->ao_color.b; + } else { + push_constant.ao_color[0] = 0; + push_constant.ao_color[1] = 0; + push_constant.ao_color[2] = 0; + } + + push_constant.cam_rotation[0] = p_transform.basis[0][0]; + push_constant.cam_rotation[1] = p_transform.basis[1][0]; + push_constant.cam_rotation[2] = p_transform.basis[2][0]; + push_constant.cam_rotation[3] = 0; + push_constant.cam_rotation[4] = p_transform.basis[0][1]; + push_constant.cam_rotation[5] = p_transform.basis[1][1]; + push_constant.cam_rotation[6] = p_transform.basis[2][1]; + push_constant.cam_rotation[7] = 0; + push_constant.cam_rotation[8] = p_transform.basis[0][2]; + push_constant.cam_rotation[9] = p_transform.basis[1][2]; + push_constant.cam_rotation[10] = p_transform.basis[2][2]; + push_constant.cam_rotation[11] = 0; + + if (rb->sdfgi) { + GI::SDFGIData sdfgi_data; + + sdfgi_data.grid_size[0] = rb->sdfgi->cascade_size; + sdfgi_data.grid_size[1] = rb->sdfgi->cascade_size; + sdfgi_data.grid_size[2] = rb->sdfgi->cascade_size; + + sdfgi_data.max_cascades = rb->sdfgi->cascades.size(); + sdfgi_data.probe_axis_size = rb->sdfgi->probe_axis_count; + sdfgi_data.cascade_probe_size[0] = sdfgi_data.probe_axis_size - 1; //float version for performance + sdfgi_data.cascade_probe_size[1] = sdfgi_data.probe_axis_size - 1; + sdfgi_data.cascade_probe_size[2] = sdfgi_data.probe_axis_size - 1; + + float csize = rb->sdfgi->cascade_size; + sdfgi_data.probe_to_uvw = 1.0 / float(sdfgi_data.cascade_probe_size[0]); + sdfgi_data.use_occlusion = rb->sdfgi->uses_occlusion; + //sdfgi_data.energy = rb->sdfgi->energy; + + sdfgi_data.y_mult = rb->sdfgi->y_mult; + + float cascade_voxel_size = (csize / sdfgi_data.cascade_probe_size[0]); + float occlusion_clamp = (cascade_voxel_size - 0.5) / cascade_voxel_size; + sdfgi_data.occlusion_clamp[0] = occlusion_clamp; + sdfgi_data.occlusion_clamp[1] = occlusion_clamp; + sdfgi_data.occlusion_clamp[2] = occlusion_clamp; + sdfgi_data.normal_bias = (rb->sdfgi->normal_bias / csize) * sdfgi_data.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; + + uint32_t oct_size = SDFGI::LIGHTPROBE_OCT_SIZE; + + sdfgi_data.lightprobe_tex_pixel_size[0] = 1.0 / ((oct_size + 2) * sdfgi_data.probe_axis_size * sdfgi_data.probe_axis_size); + sdfgi_data.lightprobe_tex_pixel_size[1] = 1.0 / ((oct_size + 2) * sdfgi_data.probe_axis_size); + sdfgi_data.lightprobe_tex_pixel_size[2] = 1.0; + + sdfgi_data.energy = rb->sdfgi->energy; + + sdfgi_data.lightprobe_uv_offset[0] = float(oct_size + 2) * sdfgi_data.lightprobe_tex_pixel_size[0]; + sdfgi_data.lightprobe_uv_offset[1] = float(oct_size + 2) * sdfgi_data.lightprobe_tex_pixel_size[1]; + sdfgi_data.lightprobe_uv_offset[2] = float((oct_size + 2) * sdfgi_data.probe_axis_size) * sdfgi_data.lightprobe_tex_pixel_size[0]; + + sdfgi_data.occlusion_renormalize[0] = 0.5; + sdfgi_data.occlusion_renormalize[1] = 1.0; + sdfgi_data.occlusion_renormalize[2] = 1.0 / float(sdfgi_data.max_cascades); + + int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; + + for (uint32_t i = 0; i < sdfgi_data.max_cascades; i++) { + GI::SDFGIData::ProbeCascadeData &c = sdfgi_data.cascades[i]; + Vector3 pos = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[i].position)) * rb->sdfgi->cascades[i].cell_size; + Vector3 cam_origin = p_transform.origin; + cam_origin.y *= rb->sdfgi->y_mult; + pos -= cam_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 / (float(rb->sdfgi->cascade_size) * rb->sdfgi->cascades[i].cell_size / float(rb->sdfgi->probe_axis_count - 1)); + + Vector3i probe_ofs = rb->sdfgi->cascades[i].position / probe_divisor; + c.probe_world_offset[0] = probe_ofs.x; + c.probe_world_offset[1] = probe_ofs.y; + c.probe_world_offset[2] = probe_ofs.z; + + c.to_cell = 1.0 / rb->sdfgi->cascades[i].cell_size; + } + + RD::get_singleton()->buffer_update(gi.sdfgi_ubo, 0, sizeof(GI::SDFGIData), &sdfgi_data, true); + } + + { + RID gi_probe_buffer = render_buffers_get_gi_probe_buffer(p_render_buffers); + GI::GIProbeData gi_probe_data[RenderBuffers::MAX_GIPROBES]; + + bool giprobes_changed = false; + + Transform to_camera; + to_camera.origin = p_transform.origin; //only translation, make local + + for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) { + RID texture; + if (i < p_gi_probe_cull_count) { + GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]); + + if (gipi) { + texture = gipi->texture; + GI::GIProbeData &gipd = gi_probe_data[i]; + + RID base_probe = gipi->probe; + + Transform to_cell = storage->gi_probe_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera; + + gipd.xform[0] = to_cell.basis.elements[0][0]; + gipd.xform[1] = to_cell.basis.elements[1][0]; + gipd.xform[2] = to_cell.basis.elements[2][0]; + gipd.xform[3] = 0; + gipd.xform[4] = to_cell.basis.elements[0][1]; + gipd.xform[5] = to_cell.basis.elements[1][1]; + gipd.xform[6] = to_cell.basis.elements[2][1]; + gipd.xform[7] = 0; + gipd.xform[8] = to_cell.basis.elements[0][2]; + gipd.xform[9] = to_cell.basis.elements[1][2]; + gipd.xform[10] = to_cell.basis.elements[2][2]; + gipd.xform[11] = 0; + gipd.xform[12] = to_cell.origin.x; + gipd.xform[13] = to_cell.origin.y; + gipd.xform[14] = to_cell.origin.z; + gipd.xform[15] = 1; + + Vector3 bounds = storage->gi_probe_get_octree_size(base_probe); + + gipd.bounds[0] = bounds.x; + gipd.bounds[1] = bounds.y; + gipd.bounds[2] = bounds.z; + + gipd.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe); + gipd.bias = storage->gi_probe_get_bias(base_probe); + gipd.normal_bias = storage->gi_probe_get_normal_bias(base_probe); + gipd.blend_ambient = !storage->gi_probe_is_interior(base_probe); + gipd.anisotropy_strength = 0; + gipd.ao = storage->gi_probe_get_ao(base_probe); + gipd.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f); + } + } + + if (texture == RID()) { + texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + } + + if (texture != rb->giprobe_textures[i]) { + giprobes_changed = true; + rb->giprobe_textures[i] = texture; + } + } + + if (giprobes_changed) { + RD::get_singleton()->free(rb->gi_uniform_set); + rb->gi_uniform_set = RID(); + } + + if (p_gi_probe_cull_count > 0) { + RD::get_singleton()->buffer_update(gi_probe_buffer, 0, sizeof(GI::GIProbeData) * MIN(RenderBuffers::MAX_GIPROBES, p_gi_probe_cull_count), gi_probe_data, true); + } + } + + if (rb->gi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->gi_uniform_set)) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[j].sdf_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[j].light_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_0_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[j].light_aniso_1_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 5; + if (rb->sdfgi) { + u.ids.push_back(rb->sdfgi->occlusion_texture); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 6; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 7; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 9; + u.ids.push_back(p_ambient_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 10; + u.ids.push_back(p_reflection_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 11; + if (rb->sdfgi) { + u.ids.push_back(rb->sdfgi->lightprobe_texture); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 12; + u.ids.push_back(rb->depth_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 13; + u.ids.push_back(p_normal_roughness_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 14; + RID buffer = p_gi_probe_buffer.is_valid() ? p_gi_probe_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 15; + u.ids.push_back(gi.sdfgi_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 16; + u.ids.push_back(rb->giprobe_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 17; + for (int i = 0; i < RenderBuffers::MAX_GIPROBES; i++) { + u.ids.push_back(rb->giprobe_textures[i]); + } + uniforms.push_back(u); + } + + rb->gi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi.shader.version_get_shader(gi.shader_version, 0), 0); + } + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi.pipelines[0]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GI::PushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1, 8, 8, 1); + RD::get_singleton()->compute_list_end(); +} + RID RasterizerSceneRD::sky_create() { return sky_owner.make_rid(Sky()); } @@ -1291,6 +2827,30 @@ void RasterizerSceneRD::environment_glow_set_use_bicubic_upscale(bool p_enable) glow_bicubic_upscale = p_enable; } +void RasterizerSceneRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->sdfgi_enabled = p_enable; + env->sdfgi_cascades = p_cascades; + env->sdfgi_min_cell_size = p_min_cell_size; + env->sdfgi_use_occlusion = p_use_occlusion; + env->sdfgi_use_multibounce = p_use_multibounce; + env->sdfgi_read_sky_light = p_read_sky; + env->sdfgi_energy = p_energy; + env->sdfgi_normal_bias = p_normal_bias; + env->sdfgi_probe_bias = p_probe_bias; + env->sdfgi_y_scale = p_y_scale; +} + +void RasterizerSceneRD::environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) { + sdfgi_ray_count = p_ray_count; +} + +void RasterizerSceneRD::environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) { + sdfgi_frames_to_converge = p_frames; +} + void RasterizerSceneRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) { Environent *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -1351,6 +2911,11 @@ bool RasterizerSceneRD::environment_is_ssr_enabled(RID p_env) const { ERR_FAIL_COND_V(!env, false); return env->ssr_enabled; } +bool RasterizerSceneRD::environment_is_sdfgi_enabled(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return env->sdfgi_enabled; +} bool RasterizerSceneRD::is_environment(RID p_env) const { return environment_owner.owns(p_env); @@ -2099,6 +3664,13 @@ void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const light_instance->transform = p_transform; } +void RasterizerSceneRD::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) { + LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->aabb = p_aabb; +} + void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) { LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); ERR_FAIL_COND(!light_instance); @@ -2193,23 +3765,9 @@ void RasterizerSceneRD::decal_instance_set_transform(RID p_decal, const Transfor ///////////////////////////////// RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) { - //find a free slot - int index = -1; - for (int i = 0; i < gi_probe_slots.size(); i++) { - if (gi_probe_slots[i] == RID()) { - index = i; - break; - } - } - - ERR_FAIL_COND_V(index == -1, RID()); - GIProbeInstance gi_probe; - gi_probe.slot = index; gi_probe.probe = p_base; RID rid = gi_probe_instance_owner.make_rid(gi_probe); - gi_probe_slots.write[index] = rid; - return rid; } @@ -2240,10 +3798,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc //need to re-create everything if (gi_probe->texture.is_valid()) { RD::get_singleton()->free(gi_probe->texture); - if (gi_probe_use_anisotropy) { - RD::get_singleton()->free(gi_probe->anisotropy_r16[0]); - RD::get_singleton()->free(gi_probe->anisotropy_r16[1]); - } RD::get_singleton()->free(gi_probe->write_buffer); gi_probe->mipmaps.clear(); } @@ -2275,47 +3829,18 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); - if (gi_probe_use_anisotropy) { - tf.format = RD::DATA_FORMAT_R16_UINT; - tf.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT); - tf.shareable_formats.push_back(RD::DATA_FORMAT_R5G6B5_UNORM_PACK16); - - //need to create R16 first, else driver does not like the storage bit for compute.. - gi_probe->anisotropy_r16[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - gi_probe->anisotropy_r16[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - RD::TextureView tv; - tv.format_override = RD::DATA_FORMAT_R5G6B5_UNORM_PACK16; - gi_probe->anisotropy[0] = RD::get_singleton()->texture_create_shared(tv, gi_probe->anisotropy_r16[0]); - gi_probe->anisotropy[1] = RD::get_singleton()->texture_create_shared(tv, gi_probe->anisotropy_r16[1]); - - RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); - RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); - } - { int total_elements = 0; for (int i = 0; i < levels.size(); i++) { total_elements += levels[i]; } - if (gi_probe_use_anisotropy) { - total_elements *= 6; - } - gi_probe->write_buffer = RD::get_singleton()->storage_buffer_create(total_elements * 16); } for (int i = 0; i < levels.size(); i++) { GIProbeInstance::Mipmap mipmap; mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), gi_probe->texture, 0, i, RD::TEXTURE_SLICE_3D); - if (gi_probe_use_anisotropy) { - RD::TextureView tv; - tv.format_override = RD::DATA_FORMAT_R16_UINT; - mipmap.anisotropy[0] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[0], 0, i, RD::TEXTURE_SLICE_3D); - mipmap.anisotropy[1] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[1], 0, i, RD::TEXTURE_SLICE_3D); - } - mipmap.level = levels.size() - i - 1; mipmap.cell_offset = 0; for (uint32_t j = 0; j < mipmap.level; j++) { @@ -2383,24 +3908,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc u.ids.push_back(gi_probe->texture); copy_uniforms.push_back(u); } - - if (gi_probe_use_anisotropy) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 7; - u.ids.push_back(gi_probe->anisotropy[0]); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 8; - u.ids.push_back(gi_probe->anisotropy[1]); - copy_uniforms.push_back(u); - } - } - mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0); } else { mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0); @@ -2415,23 +3922,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc uniforms.push_back(u); } - if (gi_probe_use_anisotropy) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 6; - u.ids.push_back(mipmap.anisotropy[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 7; - u.ids.push_back(mipmap.anisotropy[1]); - uniforms.push_back(u); - } - } - mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0); gi_probe->mipmaps.push_back(mipmap); @@ -2626,22 +4116,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].texture); uniforms.push_back(u); } - if (gi_probe_is_anisotropic()) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 12; - u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].anisotropy[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 13; - u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].anisotropy[1]); - uniforms.push_back(u); - } - } } dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT], 0); @@ -2663,10 +4137,6 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc if (gi_probe->has_dynamic_object_data) { //if it has dynamic object data, it needs to be cleared RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); - if (gi_probe_is_anisotropic()) { - RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); - RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); - } } uint32_t light_count = 0; @@ -2733,7 +4203,7 @@ void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instanc push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe); push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe); push_constant.light_count = light_count; - push_constant.aniso_strength = storage->gi_probe_get_anisotropy_strength(gi_probe->probe); + push_constant.aniso_strength = 0; /* print_line("probe update to version " + itos(gi_probe->last_probe_version)); print_line("propagation " + rtos(push_constant.propagation)); @@ -3067,23 +4537,6 @@ void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_lis uniforms.push_back(u); } - if (gi_probe_use_anisotropy) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 4; - u.ids.push_back(gi_probe->anisotropy[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 5; - u.ids.push_back(gi_probe->anisotropy[1]); - uniforms.push_back(u); - } - } - int cell_count; if (!p_emission && p_lighting && gi_probe->has_dynamic_object_data) { cell_count = push_constant.bounds[0] * push_constant.bounds[1] * push_constant.bounds[2]; @@ -3098,12 +4551,140 @@ void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_lis RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36); } -const Vector<RID> &RasterizerSceneRD::gi_probe_get_slots() const { - return gi_probe_slots; -} +void RasterizerSceneRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + if (!rb->sdfgi) { + return; //nothing to debug + } + + SDGIShader::DebugProbesPushConstant push_constant; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + push_constant.projection[i * 4 + j] = p_camera_with_transform.matrix[i][j]; + } + } + + //gen spheres from strips + uint32_t band_points = 16; + push_constant.band_power = 4; + push_constant.sections_in_band = ((band_points / 2) - 1); + push_constant.band_mask = band_points - 2; + push_constant.section_arc = (Math_PI * 2.0) / float(push_constant.sections_in_band); + push_constant.y_mult = rb->sdfgi->y_mult; + + uint32_t total_points = push_constant.sections_in_band * band_points; + uint32_t total_probes = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count; + + push_constant.grid_size[0] = rb->sdfgi->cascade_size; + push_constant.grid_size[1] = rb->sdfgi->cascade_size; + push_constant.grid_size[2] = rb->sdfgi->cascade_size; + push_constant.cascade = 0; + + push_constant.probe_axis_size = rb->sdfgi->probe_axis_count; + + if (!rb->sdfgi->debug_probes_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(rb->sdfgi->debug_probes_uniform_set)) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(rb->sdfgi->cascades_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(rb->sdfgi->lightprobe_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(rb->sdfgi->occlusion_texture); + uniforms.push_back(u); + } + + rb->sdfgi->debug_probes_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, 0), 0); + } + + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, sdfgi_shader.debug_probes_pipeline[SDGIShader::PROBE_DEBUG_PROBES].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, rb->sdfgi->debug_probes_uniform_set, 0); + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDGIShader::DebugProbesPushConstant)); + RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points); + + if (sdfgi_debug_probe_dir != Vector3()) { + print_line("CLICK DEBUG ME?"); + uint32_t cascade = 0; + Vector3 offset = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[cascade].position)) * rb->sdfgi->cascades[cascade].cell_size * Vector3(1.0, 1.0 / rb->sdfgi->y_mult, 1.0); + Vector3 probe_size = rb->sdfgi->cascades[cascade].cell_size * (rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR) * Vector3(1.0, 1.0 / rb->sdfgi->y_mult, 1.0); + Vector3 ray_from = sdfgi_debug_probe_pos; + Vector3 ray_to = sdfgi_debug_probe_pos + sdfgi_debug_probe_dir * rb->sdfgi->cascades[cascade].cell_size * Math::sqrt(3.0) * rb->sdfgi->cascade_size; + float sphere_radius = 0.2; + float closest_dist = 1e20; + sdfgi_debug_probe_enabled = false; + + Vector3i probe_from = rb->sdfgi->cascades[cascade].position / (rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR); + for (int i = 0; i < (SDFGI::PROBE_DIVISOR + 1); i++) { + for (int j = 0; j < (SDFGI::PROBE_DIVISOR + 1); j++) { + for (int k = 0; k < (SDFGI::PROBE_DIVISOR + 1); k++) { + Vector3 pos = offset + probe_size * Vector3(i, j, k); + Vector3 res; + if (Geometry3D::segment_intersects_sphere(ray_from, ray_to, pos, sphere_radius, &res)) { + float d = ray_from.distance_to(res); + if (d < closest_dist) { + closest_dist = d; + sdfgi_debug_probe_enabled = true; + sdfgi_debug_probe_index = probe_from + Vector3i(i, j, k); + } + } + } + } + } + + if (sdfgi_debug_probe_enabled) { + print_line("found: " + sdfgi_debug_probe_index); + } else { + print_line("no found"); + } + sdfgi_debug_probe_dir = Vector3(); + } + + if (sdfgi_debug_probe_enabled) { + uint32_t cascade = 0; + uint32_t probe_cells = (rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR); + Vector3i probe_from = rb->sdfgi->cascades[cascade].position / probe_cells; + Vector3i ofs = sdfgi_debug_probe_index - probe_from; + if (ofs.x < 0 || ofs.y < 0 || ofs.z < 0) { + return; + } + if (ofs.x > SDFGI::PROBE_DIVISOR || ofs.y > SDFGI::PROBE_DIVISOR || ofs.z > SDFGI::PROBE_DIVISOR) { + return; + } -RasterizerSceneRD::GIProbeQuality RasterizerSceneRD::gi_probe_get_quality() const { - return gi_probe_quality; + uint32_t mult = (SDFGI::PROBE_DIVISOR + 1); + uint32_t index = ofs.z * mult * mult + ofs.y * mult + ofs.x; + + push_constant.probe_debug_index = index; + + uint32_t cell_count = probe_cells * 2 * probe_cells * 2 * probe_cells * 2; + + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, sdfgi_shader.debug_probes_pipeline[SDGIShader::PROBE_DEBUG_VISIBILITY].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, rb->sdfgi->debug_probes_uniform_set, 0); + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDGIShader::DebugProbesPushConstant)); + RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, total_points); + } } //////////////////////////////// @@ -3273,7 +4854,7 @@ void RasterizerSceneRD::_process_sss(RID p_render_buffers, const CameraMatrix &p storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality); } -void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_roughness_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 RasterizerSceneRD::_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) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); ERR_FAIL_COND(!rb); @@ -3322,7 +4903,7 @@ void RasterizerSceneRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffe _render_buffers_uniform_set_changed(p_render_buffers); } - storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, p_roughness_buffer, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); + storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->texture, rb->blur[0].mipmaps[1].texture); } @@ -3563,15 +5144,163 @@ void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_s effects->copy_to_fb_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER && _render_buffers_get_roughness_texture(p_render_buffers).is_valid()) { + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); + effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && _render_buffers_get_ambient_texture(p_render_buffers).is_valid()) { Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + RID ambient_texture = _render_buffers_get_ambient_texture(p_render_buffers); + RID reflection_texture = _render_buffers_get_reflection_texture(p_render_buffers); + effects->copy_to_fb_rect(ambient_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture); + } +} + +void RasterizerSceneRD::_sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + if (!rb->sdfgi) { + return; //eh } + + if (!rb->sdfgi->debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(rb->sdfgi->debug_uniform_set)) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[i].sdf_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[i].light_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[i].light_aniso_0_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < rb->sdfgi->cascades.size()) { + u.ids.push_back(rb->sdfgi->cascades[i].light_aniso_1_tex); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 5; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(rb->sdfgi->occlusion_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 8; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 9; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(rb->sdfgi->cascades_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 10; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.ids.push_back(rb->texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 11; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(rb->sdfgi->lightprobe_texture); + uniforms.push_back(u); + } + rb->sdfgi->debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.debug_shader_version, 0); + } + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.debug_pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->debug_uniform_set, 0); + + SDGIShader::DebugPushConstant push_constant; + push_constant.grid_size[0] = rb->sdfgi->cascade_size; + push_constant.grid_size[1] = rb->sdfgi->cascade_size; + push_constant.grid_size[2] = rb->sdfgi->cascade_size; + push_constant.max_cascades = rb->sdfgi->cascades.size(); + push_constant.screen_size[0] = rb->width; + push_constant.screen_size[1] = rb->height; + push_constant.probe_axis_size = rb->sdfgi->probe_axis_count; + push_constant.use_occlusion = rb->sdfgi->uses_occlusion; + push_constant.y_mult = rb->sdfgi->y_mult; + + Vector2 vp_half = p_projection.get_viewport_half_extents(); + push_constant.cam_extent[0] = vp_half.x; + push_constant.cam_extent[1] = vp_half.y; + push_constant.cam_extent[2] = -p_projection.get_z_near(); + + push_constant.cam_transform[0] = p_transform.basis.elements[0][0]; + push_constant.cam_transform[1] = p_transform.basis.elements[1][0]; + push_constant.cam_transform[2] = p_transform.basis.elements[2][0]; + push_constant.cam_transform[3] = 0; + push_constant.cam_transform[4] = p_transform.basis.elements[0][1]; + push_constant.cam_transform[5] = p_transform.basis.elements[1][1]; + push_constant.cam_transform[6] = p_transform.basis.elements[2][1]; + push_constant.cam_transform[7] = 0; + push_constant.cam_transform[8] = p_transform.basis.elements[0][2]; + push_constant.cam_transform[9] = p_transform.basis.elements[1][2]; + push_constant.cam_transform[10] = p_transform.basis.elements[2][2]; + push_constant.cam_transform[11] = 0; + push_constant.cam_transform[12] = p_transform.origin.x; + push_constant.cam_transform[13] = p_transform.origin.y; + push_constant.cam_transform[14] = p_transform.origin.z; + push_constant.cam_transform[15] = 1; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::DebugPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->width, rb->height, 1, 8, 8, 1); + RD::get_singleton()->compute_list_end(); + + Size2 rtsize = storage->render_target_get_size(rb->render_target); + storage->get_effects()->copy_to_fb_rect(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), true); } RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { @@ -3590,6 +5319,113 @@ RID RasterizerSceneRD::render_buffers_get_ao_texture(RID p_render_buffers) { return rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; } +RID RasterizerSceneRD::render_buffers_get_gi_probe_buffer(RID p_render_buffers) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, RID()); + if (rb->giprobe_buffer.is_null()) { + rb->giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES); + } + return rb->giprobe_buffer; +} + +RID RasterizerSceneRD::render_buffers_get_default_gi_probe_buffer() { + return default_giprobe_buffer; +} + +uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, 0); + ERR_FAIL_COND_V(!rb->sdfgi, 0); + + return rb->sdfgi->cascades.size(); +} +bool RasterizerSceneRD::render_buffers_is_sdfgi_enabled(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, false); + + return rb->sdfgi != nullptr; +} +RID RasterizerSceneRD::render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, RID()); + ERR_FAIL_COND_V(!rb->sdfgi, RID()); + + return rb->sdfgi->lightprobe_texture; +} + +Vector3 RasterizerSceneRD::render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, Vector3()); + ERR_FAIL_COND_V(!rb->sdfgi, Vector3()); + ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3()); + + return Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[p_cascade].position)) * rb->sdfgi->cascades[p_cascade].cell_size; +} + +Vector3i RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, Vector3i()); + ERR_FAIL_COND_V(!rb->sdfgi, Vector3i()); + ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3i()); + int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; + + return rb->sdfgi->cascades[p_cascade].position / probe_divisor; +} + +float RasterizerSceneRD::render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, 0); + ERR_FAIL_COND_V(!rb->sdfgi, 0); + + return rb->sdfgi->normal_bias; +} +float RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, 0); + ERR_FAIL_COND_V(!rb->sdfgi, 0); + ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), 0); + + return float(rb->sdfgi->cascade_size) * rb->sdfgi->cascades[p_cascade].cell_size / float(rb->sdfgi->probe_axis_count - 1); +} +uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, 0); + ERR_FAIL_COND_V(!rb->sdfgi, 0); + + return rb->sdfgi->probe_axis_count; +} + +uint32_t RasterizerSceneRD::render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, 0); + ERR_FAIL_COND_V(!rb->sdfgi, 0); + + return rb->sdfgi->cascade_size; +} + +bool RasterizerSceneRD::render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, false); + ERR_FAIL_COND_V(!rb->sdfgi, false); + + return rb->sdfgi->uses_occlusion; +} + +float RasterizerSceneRD::render_buffers_get_sdfgi_energy(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, 0); + ERR_FAIL_COND_V(!rb->sdfgi, false); + + return rb->sdfgi->energy; +} +RID RasterizerSceneRD::render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const { + const RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, RID()); + ERR_FAIL_COND_V(!rb->sdfgi, RID()); + + return rb->sdfgi->occlusion_texture; +} + void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); rb->width = p_width; @@ -3606,7 +5442,7 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren tf.height = rb->height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; } else { tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } @@ -3616,12 +5452,20 @@ void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_ren { RD::TextureFormat tf; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) { + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + } else { + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + } + tf.width = p_width; tf.height = p_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + } else { + tf.usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; } rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); @@ -3748,6 +5592,14 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca clear_color = storage->get_default_clear_color(); } + //assign render indices to giprobes + for (int i = 0; i < p_gi_probe_cull_count; i++) { + GIProbeInstance *giprobe_inst = gi_probe_instance_owner.getornull(p_gi_probe_cull_result[i]); + if (giprobe_inst) { + giprobe_inst->render_index = i; + } + } + _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_decal_cull_result, p_decal_cull_count, p_lightmap_cull_result, p_lightmap_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color); if (p_render_buffers.is_valid()) { @@ -3755,6 +5607,9 @@ void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_ca _render_buffers_post_process_and_tonemap(p_render_buffers, p_environment, p_camera_effects, p_cam_projection); _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas); + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI) { + _sdfgi_debug_draw(p_render_buffers, p_cam_projection, p_cam_transform); + } } } @@ -3938,11 +5793,455 @@ void RasterizerSceneRD::render_material(const Transform &p_cam_transform, const _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_framebuffer, p_region); } +void RasterizerSceneRD::render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count) { + //print_line("rendering region " + itos(p_region)); + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + ERR_FAIL_COND(!rb->sdfgi); + AABB bounds; + Vector3i from; + Vector3i size; + + int cascade_prev = _sdfgi_get_pending_region_data(p_render_buffers, p_region - 1, from, size, bounds); + int cascade_next = _sdfgi_get_pending_region_data(p_render_buffers, p_region + 1, from, size, bounds); + int cascade = _sdfgi_get_pending_region_data(p_render_buffers, p_region, from, size, bounds); + ERR_FAIL_COND(cascade < 0); + + if (cascade_prev != cascade) { + //initialize render + RD::get_singleton()->texture_clear(rb->sdfgi->render_albedo, Color(0, 0, 0, 0), 0, 1, 0, 1, true); + RD::get_singleton()->texture_clear(rb->sdfgi->render_emission, Color(0, 0, 0, 0), 0, 1, 0, 1, true); + RD::get_singleton()->texture_clear(rb->sdfgi->render_emission_aniso, Color(0, 0, 0, 0), 0, 1, 0, 1, true); + RD::get_singleton()->texture_clear(rb->sdfgi->render_geom_facing, Color(0, 0, 0, 0), 0, 1, 0, 1, true); + } + + //print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(rb->sdfgi->cascades[cascade].cell_size)); + _render_sdfgi(p_render_buffers, from, size, bounds, p_cull_result, p_cull_count, rb->sdfgi->render_albedo, rb->sdfgi->render_emission, rb->sdfgi->render_emission_aniso, rb->sdfgi->render_geom_facing); + + if (cascade_next != cascade) { + RENDER_TIMESTAMP(">SDFGI Update SDF"); + //done rendering! must update SDF + //clear dispatch indirect data + + SDGIShader::PreprocessPushConstant push_constant; + zeromem(&push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + + RENDER_TIMESTAMP("Scroll SDF"); + + //scroll + if (rb->sdfgi->cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) { + //for scroll + Vector3i dirty = rb->sdfgi->cascades[cascade].dirty_regions; + push_constant.scroll[0] = dirty.x; + push_constant.scroll[1] = dirty.y; + push_constant.scroll[2] = dirty.z; + } else { + //for no scroll + push_constant.scroll[0] = 0; + push_constant.scroll[1] = 0; + push_constant.scroll[2] = 0; + } + push_constant.grid_size = rb->sdfgi->cascade_size; + push_constant.cascade = cascade; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + if (rb->sdfgi->cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) { + //must pre scroll existing data because not all is dirty + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_SCROLL]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].scroll_uniform_set, 0); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_indirect(compute_list, rb->sdfgi->cascades[cascade].solid_cell_dispatch_buffer, 0); + // no barrier do all together + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_SCROLL_OCCLUSION]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].scroll_occlusion_uniform_set, 0); + + Vector3i dirty = rb->sdfgi->cascades[cascade].dirty_regions; + Vector3i groups; + groups.x = rb->sdfgi->cascade_size - ABS(dirty.x); + groups.y = rb->sdfgi->cascade_size - ABS(dirty.y); + groups.z = rb->sdfgi->cascade_size - ABS(dirty.z); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, groups.x, groups.y, groups.z, 4, 4, 4); + + //no barrier, continue together + + { + //scroll probes and their history also + + SDGIShader::IntegratePushConstant ipush_constant; + ipush_constant.grid_size[1] = rb->sdfgi->cascade_size; + ipush_constant.grid_size[2] = rb->sdfgi->cascade_size; + ipush_constant.grid_size[0] = rb->sdfgi->cascade_size; + ipush_constant.max_cascades = rb->sdfgi->cascades.size(); + ipush_constant.probe_axis_size = rb->sdfgi->probe_axis_count; + ipush_constant.history_index = 0; + ipush_constant.history_size = rb->sdfgi->history_size; + ipush_constant.ray_count = 0; + ipush_constant.ray_bias = 0; + ipush_constant.sky_mode = 0; + ipush_constant.sky_energy = 0; + ipush_constant.sky_color[0] = 0; + ipush_constant.sky_color[1] = 0; + ipush_constant.sky_color[2] = 0; + ipush_constant.y_mult = rb->sdfgi->y_mult; + + ipush_constant.image_size[0] = rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count; + ipush_constant.image_size[1] = rb->sdfgi->probe_axis_count; + ipush_constant.image_size[1] = rb->sdfgi->probe_axis_count; + + int32_t probe_divisor = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; + ipush_constant.cascade = cascade; + ipush_constant.world_offset[0] = rb->sdfgi->cascades[cascade].position.x / probe_divisor; + ipush_constant.world_offset[1] = rb->sdfgi->cascades[cascade].position.y / probe_divisor; + ipush_constant.world_offset[2] = rb->sdfgi->cascades[cascade].position.z / probe_divisor; + + ipush_constant.scroll[0] = dirty.x / probe_divisor; + ipush_constant.scroll[1] = dirty.y / probe_divisor; + ipush_constant.scroll[2] = dirty.z / probe_divisor; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_SCROLL]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].integrate_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdfgi_shader.integrate_default_sky_uniform_set, 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDGIShader::IntegratePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count, rb->sdfgi->probe_axis_count, 1, 8, 8, 1); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.integrate_pipeline[SDGIShader::INTEGRATE_MODE_SCROLL_STORE]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].integrate_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, sdfgi_shader.integrate_default_sky_uniform_set, 1); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ipush_constant, sizeof(SDGIShader::IntegratePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->probe_axis_count * rb->sdfgi->probe_axis_count, rb->sdfgi->probe_axis_count, 1, 8, 8, 1); + } + + //ok finally barrier + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + + //clear dispatch indirect data + uint32_t dispatch_indirct_data[4] = { 0, 0, 0, 0 }; + RD::get_singleton()->buffer_update(rb->sdfgi->cascades[cascade].solid_cell_dispatch_buffer, 0, sizeof(uint32_t) * 4, dispatch_indirct_data, true); + + bool half_size = true; //much faster, very little differnce + static const int optimized_jf_group_size = 8; + + if (half_size) { + push_constant.grid_size >>= 1; + + uint32_t cascade_half_size = rb->sdfgi->cascade_size >> 1; + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->sdf_initialize_half_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size, 4, 4, 4); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //must start with regular jumpflood + + push_constant.half_size = true; + { + RENDER_TIMESTAMP("SDFGI Jump Flood (Half Size)"); + + uint32_t s = cascade_half_size; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD]); + + int jf_us = 0; + //start with regular jump flood for very coarse reads, as this is impossible to optimize + while (s > 1) { + s /= 2; + push_constant.step_size = s; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_half_uniform_set[jf_us], 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size, 4, 4, 4); + RD::get_singleton()->compute_list_add_barrier(compute_list); + jf_us = jf_us == 0 ? 1 : 0; + + if (cascade_half_size / (s / 2) >= optimized_jf_group_size) { + break; + } + } + + RENDER_TIMESTAMP("SDFGI Jump Flood Optimized (Half Size)"); + + //continue with optimized jump flood for smaller reads + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]); + while (s > 1) { + s /= 2; + push_constant.step_size = s; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_half_uniform_set[jf_us], 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, cascade_half_size, cascade_half_size, cascade_half_size, optimized_jf_group_size, optimized_jf_group_size, optimized_jf_group_size); + RD::get_singleton()->compute_list_add_barrier(compute_list); + jf_us = jf_us == 0 ? 1 : 0; + } + } + + // restore grid size for last passes + push_constant.grid_size = rb->sdfgi->cascade_size; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_UPSCALE]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->sdf_upscale_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //run one pass of fullsize jumpflood to fix up half size arctifacts + + push_constant.half_size = false; + push_constant.step_size = 1; + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_uniform_set[rb->sdfgi->upscale_jfa_uniform_set_index], 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, optimized_jf_group_size, optimized_jf_group_size, optimized_jf_group_size); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + } else { + //full size jumpflood + RENDER_TIMESTAMP("SDFGI Jump Flood"); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_INITIALIZE]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->sdf_initialize_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4); + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + push_constant.half_size = false; + { + uint32_t s = rb->sdfgi->cascade_size; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD]); + + int jf_us = 0; + //start with regular jump flood for very coarse reads, as this is impossible to optimize + while (s > 1) { + s /= 2; + push_constant.step_size = s; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_uniform_set[jf_us], 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4); + RD::get_singleton()->compute_list_add_barrier(compute_list); + jf_us = jf_us == 0 ? 1 : 0; + + if (rb->sdfgi->cascade_size / (s / 2) >= optimized_jf_group_size) { + break; + } + } + + RENDER_TIMESTAMP("SDFGI Jump Flood Optimized"); + + //continue with optimized jump flood for smaller reads + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_JUMP_FLOOD_OPTIMIZED]); + while (s > 1) { + s /= 2; + push_constant.step_size = s; + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->jump_flood_uniform_set[jf_us], 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, optimized_jf_group_size, optimized_jf_group_size, optimized_jf_group_size); + RD::get_singleton()->compute_list_add_barrier(compute_list); + jf_us = jf_us == 0 ? 1 : 0; + } + } + } + + RENDER_TIMESTAMP("SDFGI Occlusion"); + + // occlusion + { + uint32_t probe_size = rb->sdfgi->cascade_size / SDFGI::PROBE_DIVISOR; + Vector3i probe_global_pos = rb->sdfgi->cascades[cascade].position / probe_size; + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_OCCLUSION]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->occlusion_uniform_set, 0); + for (int i = 0; i < 8; i++) { + //dispatch all at once for performance + Vector3i offset(i & 1, (i >> 1) & 1, (i >> 2) & 1); + + if ((probe_global_pos.x & 1) != 0) { + offset.x = (offset.x + 1) & 1; + } + if ((probe_global_pos.y & 1) != 0) { + offset.y = (offset.y + 1) & 1; + } + if ((probe_global_pos.z & 1) != 0) { + offset.z = (offset.z + 1) & 1; + } + push_constant.probe_offset[0] = offset.x; + push_constant.probe_offset[1] = offset.y; + push_constant.probe_offset[2] = offset.z; + push_constant.occlusion_index = i; + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + + Vector3i groups = Vector3i(probe_size + 1, probe_size + 1, probe_size + 1) - offset; //if offseted, its one less probe per axis to compute + RD::get_singleton()->compute_list_dispatch(compute_list, groups.x, groups.y, groups.z); + } + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + + RENDER_TIMESTAMP("SDFGI Store"); + + // store + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_STORE]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].sdf_store_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDGIShader::PreprocessPushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, 4, 4, 4); + + RD::get_singleton()->compute_list_end(); + + //clear these textures, as they will have previous garbage on next draw + RD::get_singleton()->texture_clear(rb->sdfgi->cascades[cascade].light_tex, Color(0, 0, 0, 0), 0, 1, 0, 1, true); + RD::get_singleton()->texture_clear(rb->sdfgi->cascades[cascade].light_aniso_0_tex, Color(0, 0, 0, 0), 0, 1, 0, 1, true); + RD::get_singleton()->texture_clear(rb->sdfgi->cascades[cascade].light_aniso_1_tex, Color(0, 0, 0, 0), 0, 1, 0, 1, true); + +#if 0 + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rb->sdfgi->cascades[cascade].sdf, 0); + Ref<Image> img; + img.instance(); + for (uint32_t i = 0; i < rb->sdfgi->cascade_size; i++) { + Vector<uint8_t> subarr = data.subarray(128 * 128 * i, 128 * 128 * (i + 1) - 1); + img->create(rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, false, Image::FORMAT_L8, subarr); + img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png"); + } + + //finalize render and update sdf +#endif + +#if 0 + Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rb->sdfgi->render_albedo, 0); + Ref<Image> img; + img.instance(); + for (uint32_t i = 0; i < rb->sdfgi->cascade_size; i++) { + Vector<uint8_t> subarr = data.subarray(128 * 128 * i * 2, 128 * 128 * (i + 1) * 2 - 1); + img->create(rb->sdfgi->cascade_size, rb->sdfgi->cascade_size, false, Image::FORMAT_RGB565, subarr); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://cascade_" + itos(cascade) + "_" + itos(i) + ".png"); + } + + //finalize render and update sdf +#endif + + RENDER_TIMESTAMP("<SDFGI Update SDF"); + } +} + +void RasterizerSceneRD::render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + ERR_FAIL_COND(!rb->sdfgi); + + ERR_FAIL_COND(p_positional_light_cull_count == 0); + + _sdfgi_update_cascades(p_render_buffers); //need cascades updated for this + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.direct_light_pipeline[SDGIShader::DIRECT_LIGHT_MODE_STATIC]); + + SDGIShader::DirectLightPushConstant dl_push_constant; + + dl_push_constant.grid_size[0] = rb->sdfgi->cascade_size; + dl_push_constant.grid_size[1] = rb->sdfgi->cascade_size; + dl_push_constant.grid_size[2] = rb->sdfgi->cascade_size; + dl_push_constant.max_cascades = rb->sdfgi->cascades.size(); + dl_push_constant.probe_axis_size = rb->sdfgi->probe_axis_count; + dl_push_constant.multibounce = false; // this is static light, do not multibounce yet + dl_push_constant.y_mult = rb->sdfgi->y_mult; + + //all must be processed + dl_push_constant.process_offset = 0; + dl_push_constant.process_increment = 1; + + SDGIShader::Light lights[SDFGI::MAX_STATIC_LIGHTS]; + + for (uint32_t i = 0; i < p_cascade_count; i++) { + ERR_CONTINUE(p_cascade_indices[i] >= rb->sdfgi->cascades.size()); + + SDFGI::Cascade &cc = rb->sdfgi->cascades[p_cascade_indices[i]]; + + { //fill light buffer + + AABB cascade_aabb; + cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + cc.position)) * cc.cell_size; + cascade_aabb.size = Vector3(1, 1, 1) * rb->sdfgi->cascade_size * cc.cell_size; + + int idx = 0; + + for (uint32_t j = 0; j < p_positional_light_cull_count[i]; j++) { + if (idx == SDFGI::MAX_STATIC_LIGHTS) { + break; + } + + LightInstance *li = light_instance_owner.getornull(p_positional_light_cull_result[i][j]); + ERR_CONTINUE(!li); + + uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light); + if (p_cascade_indices[i] > max_sdfgi_cascade) { + continue; + } + + if (!cascade_aabb.intersects(li->aabb)) { + continue; + } + + lights[idx].type = storage->light_get_type(li->light); + + Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); + if (lights[idx].type == RS::LIGHT_DIRECTIONAL) { + dir.y *= rb->sdfgi->y_mult; //only makes sense for directional + dir.normalize(); + } + lights[idx].direction[0] = dir.x; + lights[idx].direction[1] = dir.y; + lights[idx].direction[2] = dir.z; + Vector3 pos = li->transform.origin; + pos.y *= rb->sdfgi->y_mult; + lights[idx].position[0] = pos.x; + lights[idx].position[1] = pos.y; + lights[idx].position[2] = pos.z; + Color color = storage->light_get_color(li->light); + color = color.to_linear(); + lights[idx].color[0] = color.r; + lights[idx].color[1] = color.g; + lights[idx].color[2] = color.b; + lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].has_shadow = storage->light_has_shadow(li->light); + lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); + lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); + lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)); + lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + idx++; + } + + if (idx > 0) { + RD::get_singleton()->buffer_update(cc.lights_buffer, 0, idx * sizeof(SDGIShader::Light), lights, true); + } + dl_push_constant.light_count = idx; + } + + dl_push_constant.cascade = p_cascade_indices[i]; + + if (dl_push_constant.light_count > 0) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDGIShader::DirectLightPushConstant)); + RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0); + } + } + + RD::get_singleton()->compute_list_end(); +} + bool RasterizerSceneRD::free(RID p_rid) { if (render_buffers_owner.owns(p_rid)) { RenderBuffers *rb = render_buffers_owner.getornull(p_rid); _free_render_buffer_data(rb); memdelete(rb->data); + if (rb->sdfgi) { + _sdfgi_erase(rb); + } render_buffers_owner.free(p_rid); } else if (environment_owner.owns(p_rid)) { //not much to delete, just free it @@ -3966,18 +6265,12 @@ bool RasterizerSceneRD::free(RID p_rid) { RD::get_singleton()->free(gi_probe->texture); RD::get_singleton()->free(gi_probe->write_buffer); } - if (gi_probe->anisotropy[0].is_valid()) { - RD::get_singleton()->free(gi_probe->anisotropy[0]); - RD::get_singleton()->free(gi_probe->anisotropy[1]); - } for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) { RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture); RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth); } - gi_probe_slots.write[gi_probe->slot] = RID(); - gi_probe_instance_owner.free(p_rid); } else if (sky_owner.owns(p_rid)) { _update_dirty_skys(); @@ -4050,17 +6343,22 @@ void RasterizerSceneRD::set_time(double p_time, double p_step) { time_step = p_step; } -void RasterizerSceneRD::screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) { +void RasterizerSceneRD::screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) { screen_space_roughness_limiter = p_enable; - screen_space_roughness_limiter_curve = p_curve; + screen_space_roughness_limiter_amount = p_amount; + screen_space_roughness_limiter_limit = p_limit; } bool RasterizerSceneRD::screen_space_roughness_limiter_is_active() const { return screen_space_roughness_limiter; } -float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const { - return screen_space_roughness_limiter_curve; +float RasterizerSceneRD::screen_space_roughness_limiter_get_amount() const { + return screen_space_roughness_limiter_amount; +} + +float RasterizerSceneRD::screen_space_roughness_limiter_get_limit() const { + return screen_space_roughness_limiter_limit; } TypedArray<Image> RasterizerSceneRD::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) { @@ -4154,6 +6452,11 @@ TypedArray<Image> RasterizerSceneRD::bake_render_uv2(RID p_base, const Vector<RI return ret; } +void RasterizerSceneRD::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { + sdfgi_debug_probe_pos = p_position; + sdfgi_debug_probe_dir = p_dir; +} + RasterizerSceneRD *RasterizerSceneRD::singleton = nullptr; RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { @@ -4165,7 +6468,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections"); // sky_use_cubemap_array = false; - uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + //uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); { //kinda complicated to compute the amount of slots, we try to use as many as we can @@ -4174,34 +6477,9 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights); gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight)); - - gi_probe_use_anisotropy = GLOBAL_GET("rendering/quality/gi_probes/anisotropic"); - gi_probe_quality = GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/quality/gi_probes/quality")), 0, 2)); - - if (textures_per_stage <= 16) { - gi_probe_slots.resize(2); //thats all you can get - gi_probe_use_anisotropy = false; - } else if (textures_per_stage <= 31) { - gi_probe_slots.resize(4); //thats all you can get, iOS - gi_probe_use_anisotropy = false; - } else if (textures_per_stage <= 128) { - gi_probe_slots.resize(32); //old intel - gi_probe_use_anisotropy = false; - } else if (textures_per_stage <= 256) { - gi_probe_slots.resize(64); //old intel too - gi_probe_use_anisotropy = false; - } else { - if (gi_probe_use_anisotropy) { - gi_probe_slots.resize(1024 / 3); //needs 3 textures - } else { - gi_probe_slots.resize(1024); //modern intel, nvidia, 8192 or greater - } - } + gi_probe_quality = RS::GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/quality/gi_probes/quality")), 0, 1)); String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n"; - if (gi_probe_use_anisotropy) { - defines += "\n#define MODE_ANISOTROPIC\n"; - } Vector<String> versions; versions.push_back("\n#define MODE_COMPUTE_LIGHT\n"); @@ -4223,9 +6501,6 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { { String defines; - if (gi_probe_use_anisotropy) { - defines += "\n#define USE_ANISOTROPY\n"; - } Vector<String> versions; versions.push_back("\n#define MODE_DEBUG_COLOR\n"); versions.push_back("\n#define MODE_DEBUG_LIGHT\n"); @@ -4373,11 +6648,131 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS); } + { + Vector<String> preprocess_modes; + preprocess_modes.push_back("\n#define MODE_SCROLL\n"); + preprocess_modes.push_back("\n#define MODE_SCROLL_OCCLUSION\n"); + preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD\n"); + preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD_HALF\n"); + preprocess_modes.push_back("\n#define MODE_JUMPFLOOD\n"); + preprocess_modes.push_back("\n#define MODE_JUMPFLOOD_OPTIMIZED\n"); + preprocess_modes.push_back("\n#define MODE_UPSCALE_JUMP_FLOOD\n"); + preprocess_modes.push_back("\n#define MODE_OCCLUSION\n"); + preprocess_modes.push_back("\n#define MODE_STORE\n"); + String defines = "\n#define OCCLUSION_SIZE " + itos(SDFGI::CASCADE_SIZE / SDFGI::PROBE_DIVISOR) + "\n"; + sdfgi_shader.preprocess.initialize(preprocess_modes, defines); + sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create(); + for (int i = 0; i < SDGIShader::PRE_PROCESS_MAX; i++) { + sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i)); + } + } + + { + //calculate tables + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + + Vector<String> direct_light_modes; + direct_light_modes.push_back("\n#define MODE_PROCESS_STATIC\n"); + direct_light_modes.push_back("\n#define MODE_PROCESS_DYNAMIC\n"); + sdfgi_shader.direct_light.initialize(direct_light_modes, defines); + sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create(); + for (int i = 0; i < SDGIShader::DIRECT_LIGHT_MODE_MAX; i++) { + sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i)); + } + } + + { + //calculate tables + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n"; + + Vector<String> integrate_modes; + integrate_modes.push_back("\n#define MODE_PROCESS\n"); + integrate_modes.push_back("\n#define MODE_STORE\n"); + integrate_modes.push_back("\n#define MODE_SCROLL\n"); + integrate_modes.push_back("\n#define MODE_SCROLL_STORE\n"); + sdfgi_shader.integrate.initialize(integrate_modes, defines); + sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create(); + + for (int i = 0; i < SDGIShader::INTEGRATE_MODE_MAX; i++) { + sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i)); + } + + { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 1; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1); + } + } + { + //calculate tables + String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + Vector<String> gi_modes; + gi_modes.push_back(""); + gi.shader.initialize(gi_modes, defines); + gi.shader_version = gi.shader.version_create(); + for (int i = 0; i < GI::MODE_MAX; i++) { + gi.pipelines[i] = RD::get_singleton()->compute_pipeline_create(gi.shader.version_get_shader(gi.shader_version, i)); + } + + gi.sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(GI::SDFGIData)); + } + { + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + Vector<String> debug_modes; + debug_modes.push_back(""); + sdfgi_shader.debug.initialize(debug_modes, defines); + sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create(); + sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0); + sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version); + } + { + String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; + + Vector<String> versions; + versions.push_back("\n#define MODE_PROBES\n"); + versions.push_back("\n#define MODE_VISIBILITY\n"); + + sdfgi_shader.debug_probes.initialize(versions, defines); + sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create(); + + { + RD::PipelineRasterizationState rs; + rs.cull_mode = RD::POLYGON_CULL_DISABLED; + RD::PipelineDepthStencilState ds; + ds.enable_depth_test = true; + ds.enable_depth_write = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; + for (int i = 0; i < SDGIShader::PROBE_DEBUG_MAX; i++) { + RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i); + sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + } + } + } + + default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES); + camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_shape")))); camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/depth_of_field/depth_of_field_use_jitter")); environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); - screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter"); - screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_curve"); + screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled"); + screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_amount"); + screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/quality/screen_filters/screen_space_roughness_limiter_limit"); glow_bicubic_upscale = int(GLOBAL_GET("rendering/quality/glow/upscale_mode")) > 0; ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/quality/screen_space_reflection/roughness_quality"))); sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/quality/subsurface_scattering/subsurface_scattering_quality"))); @@ -4406,9 +6801,19 @@ RasterizerSceneRD::~RasterizerSceneRD() { RD::get_singleton()->free(sky_scene_state.light_uniform_set); } + RD::get_singleton()->free(default_giprobe_buffer); RD::get_singleton()->free(gi_probe_lights_uniform); + RD::get_singleton()->free(gi.sdfgi_ubo); + giprobe_debug_shader.version_free(giprobe_debug_shader_version); giprobe_shader.version_free(giprobe_lighting_shader_version); + gi.shader.version_free(gi.shader_version); + sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader); + sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader); + sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader); + sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader); + sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader); + memdelete_arr(gi_probe_lights); SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY); sky_shader.shader.version_free(md->shader_data->version); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h index 781dbd50cc..83c03399ab 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -31,22 +31,22 @@ #ifndef RASTERIZER_SCENE_RD_H #define RASTERIZER_SCENE_RD_H +#include "core/local_vector.h" #include "core/rid_owner.h" #include "servers/rendering/rasterizer.h" #include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" +#include "servers/rendering/rasterizer_rd/shaders/gi.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/giprobe.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl.gen.h" #include "servers/rendering/rasterizer_rd/shaders/sky.glsl.gen.h" #include "servers/rendering/rendering_device.h" class RasterizerSceneRD : public RasterizerScene { -public: - enum GIProbeQuality { - GIPROBE_QUALITY_ULTRA_LOW, - GIPROBE_QUALITY_MEDIUM, - GIPROBE_QUALITY_HIGH, - }; - protected: double time; @@ -81,23 +81,27 @@ protected: virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake) = 0; virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; virtual void _render_uv2(InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; + virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, InstanceBase **p_cull_result, int p_cull_count, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform); RenderBufferData *render_buffers_get_data(RID p_render_buffers); virtual void _base_uniforms_changed() = 0; virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0; - virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers) = 0; virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0; + virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers) = 0; + virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers) = 0; void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection); - void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_roughness_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_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); void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size); void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); void _draw_sky(bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); + void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count); private: RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; @@ -267,6 +271,8 @@ private: SkyMaterialData *prev_material; Vector3 prev_position; float prev_time; + + RID sdfgi_integrate_sky_uniform_set; }; Sky *dirty_sky_list = nullptr; @@ -388,13 +394,10 @@ private: struct GIProbeInstance { RID probe; RID texture; - RID anisotropy[2]; //only if anisotropy is used - RID anisotropy_r16[2]; //only if anisotropy is used RID write_buffer; struct Mipmap { RID texture; - RID anisotropy[2]; //only if anisotropy is used RID uniform_set; RID second_bounce_uniform_set; RID write_uniform_set; @@ -423,7 +426,7 @@ private: uint32_t last_probe_version = 0; uint32_t last_probe_data_version = 0; - uint64_t last_pass = 0; + //uint64_t last_pass = 0; uint32_t render_index = 0; bool has_dynamic_object_data = false; @@ -435,11 +438,6 @@ private: uint32_t gi_probe_max_lights; RID gi_probe_lights_uniform; - bool gi_probe_use_anisotropy = false; - GIProbeQuality gi_probe_quality = GIPROBE_QUALITY_MEDIUM; - - Vector<RID> gi_probe_slots; - enum { GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT, GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE, @@ -458,6 +456,8 @@ private: mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner; + RS::GIProbeQuality gi_probe_quality = RS::GI_PROBE_QUALITY_HIGH; + enum { GI_PROBE_DEBUG_COLOR, GI_PROBE_DEBUG_LIGHT, @@ -591,6 +591,7 @@ private: ShadowTransform shadow_transform[4]; + AABB aabb; RID self; RID light; Transform transform; @@ -680,6 +681,18 @@ private: float ssr_fade_in = 0.15; float ssr_fade_out = 2.0; float ssr_depth_tolerance = 0.2; + + /// SDFGI + bool sdfgi_enabled = false; + RS::EnvironmentSDFGICascades sdfgi_cascades; + float sdfgi_min_cell_size = 0.2; + bool sdfgi_use_occlusion = false; + bool sdfgi_use_multibounce = false; + bool sdfgi_read_sky_light = false; + float sdfgi_energy = 1.0; + float sdfgi_normal_bias = 1.1; + float sdfgi_probe_bias = 1.1; + RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_DISABLED; }; RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; @@ -719,7 +732,13 @@ private: /* RENDER BUFFERS */ + struct SDFGI; + struct RenderBuffers { + enum { + MAX_GIPROBES = 8 + }; + RenderBufferData *data = nullptr; int width = 0, height = 0; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; @@ -732,6 +751,9 @@ private: RID texture; //main texture for rendering to, must be filled after done rendering RID depth_texture; //main depth texture + RID gi_uniform_set; + SDFGI *sdfgi = nullptr; + //built-in textures used for ping pong image processing and blurring struct Blur { RID texture; @@ -764,10 +786,389 @@ private: RID depth_scaled; RID blur_radius[2]; } ssr; + + RID giprobe_textures[MAX_GIPROBES]; + RID giprobe_buffer; }; + RID default_giprobe_buffer; + + /* SDFGI */ + + struct SDFGI { + enum { + MAX_CASCADES = 8, + CASCADE_SIZE = 128, + PROBE_DIVISOR = 16, + ANISOTROPY_SIZE = 6, + MAX_DYNAMIC_LIGHTS = 128, + MAX_STATIC_LIGHTS = 1024, + LIGHTPROBE_OCT_SIZE = 6, + SH_SIZE = 16 + }; + + struct Cascade { + struct UBO { + float offset[3]; + float to_cell; + int32_t probe_offset[3]; + uint32_t pad; + }; + + //cascade blocks are full-size for volume (128^3), half size for albedo/emission + RID sdf_tex; + RID light_tex; + RID light_aniso_0_tex; + RID light_aniso_1_tex; + + RID light_data; + RID light_aniso_0_data; + RID light_aniso_1_data; + + struct SolidCell { // this struct is unused, but remains as reference for size + uint32_t position; + uint32_t albedo; + uint32_t static_light; + uint32_t static_light_aniso; + }; + + RID solid_cell_dispatch_buffer; //buffer for indirect compute dispatch + RID solid_cell_buffer; + + RID lightprobe_history_tex; + RID lightprobe_average_tex; + + float cell_size; + Vector3i position; + + static const Vector3i DIRTY_ALL; + Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all. + + RID sdf_store_uniform_set; + RID sdf_direct_light_uniform_set; + RID scroll_uniform_set; + RID scroll_occlusion_uniform_set; + RID integrate_uniform_set; + RID lights_buffer; + }; + + //used for rendering (voxelization) + RID render_albedo; + RID render_emission; + RID render_emission_aniso; + RID render_occlusion[8]; + RID render_geom_facing; + + RID render_sdf[2]; + RID render_sdf_half[2]; + + //used for ping pong processing in cascades + RID sdf_initialize_uniform_set; + RID sdf_initialize_half_uniform_set; + RID jump_flood_uniform_set[2]; + RID jump_flood_half_uniform_set[2]; + RID sdf_upscale_uniform_set; + int upscale_jfa_uniform_set_index; + RID occlusion_uniform_set; + + uint32_t cascade_size = 128; + + LocalVector<Cascade> cascades; + + RID lightprobe_texture; + RID lightprobe_data; + RID occlusion_texture; + RID occlusion_data; + + RID lightprobe_history_scroll; //used for scrolling lightprobes + RID lightprobe_average_scroll; //used for scrolling lightprobes + + uint32_t history_size = 0; + float solid_cell_ratio = 0; + uint32_t solid_cell_count = 0; + + RS::EnvironmentSDFGICascades cascade_mode; + float min_cell_size = 0; + uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints + + RID debug_uniform_set; + RID debug_probes_uniform_set; + RID cascades_ubo; + + bool uses_occlusion = false; + bool uses_multibounce = false; + bool reads_sky = false; + float energy = 1.0; + float normal_bias = 1.1; + float probe_bias = 1.1; + RS::EnvironmentSDFGIYScale y_scale_mode = RS::ENV_SDFGI_Y_SCALE_DISABLED; + + float y_mult = 1.0; + + uint32_t render_pass = 0; + }; + + RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16; + RS::EnvironmentSDFGIFramesToConverge sdfgi_frames_to_converge = RS::ENV_SDFGI_CONVERGE_IN_10_FRAMES; + float sdfgi_solid_cell_ratio = 0.25; + Vector3 sdfgi_debug_probe_pos; + Vector3 sdfgi_debug_probe_dir; + bool sdfgi_debug_probe_enabled = false; + Vector3i sdfgi_debug_probe_index; + + struct SDGIShader { + enum SDFGIPreprocessShaderVersion { + PRE_PROCESS_SCROLL, + PRE_PROCESS_SCROLL_OCCLUSION, + PRE_PROCESS_JUMP_FLOOD_INITIALIZE, + PRE_PROCESS_JUMP_FLOOD_INITIALIZE_HALF, + PRE_PROCESS_JUMP_FLOOD, + PRE_PROCESS_JUMP_FLOOD_OPTIMIZED, + PRE_PROCESS_JUMP_FLOOD_UPSCALE, + PRE_PROCESS_OCCLUSION, + PRE_PROCESS_STORE, + PRE_PROCESS_MAX + }; + + struct PreprocessPushConstant { + int32_t scroll[3]; + int32_t grid_size; + + int32_t probe_offset[3]; + int32_t step_size; + + int32_t half_size; + uint32_t occlusion_index; + int32_t cascade; + uint32_t pad; + }; + + SdfgiPreprocessShaderRD preprocess; + RID preprocess_shader; + RID preprocess_pipeline[PRE_PROCESS_MAX]; + + struct DebugPushConstant { + float grid_size[3]; + uint32_t max_cascades; + + int32_t screen_size[2]; + uint32_t use_occlusion; + float y_mult; + + float cam_extent[3]; + uint32_t probe_axis_size; + + float cam_transform[16]; + }; + + SdfgiDebugShaderRD debug; + RID debug_shader; + RID debug_shader_version; + RID debug_pipeline; + + enum ProbeDebugMode { + PROBE_DEBUG_PROBES, + PROBE_DEBUG_VISIBILITY, + PROBE_DEBUG_MAX + }; + + struct DebugProbesPushConstant { + float projection[16]; + + uint32_t band_power; + uint32_t sections_in_band; + uint32_t band_mask; + float section_arc; + + float grid_size[3]; + uint32_t cascade; + + uint32_t pad; + float y_mult; + int32_t probe_debug_index; + int32_t probe_axis_size; + }; + + SdfgiDebugProbesShaderRD debug_probes; + RID debug_probes_shader; + RID debug_probes_shader_version; + + RenderPipelineVertexFormatCacheRD debug_probes_pipeline[PROBE_DEBUG_MAX]; + + struct Light { + float color[3]; + float energy; + + float direction[3]; + uint32_t has_shadow; + + float position[3]; + float attenuation; + + uint32_t type; + float spot_angle; + float spot_attenuation; + float radius; + + float shadow_color[4]; + }; + + struct DirectLightPushConstant { + float grid_size[3]; + uint32_t max_cascades; + + uint32_t cascade; + uint32_t light_count; + uint32_t process_offset; + uint32_t process_increment; + + int32_t probe_axis_size; + uint32_t multibounce; + float y_mult; + uint32_t pad; + }; + + enum { + DIRECT_LIGHT_MODE_STATIC, + DIRECT_LIGHT_MODE_DYNAMIC, + DIRECT_LIGHT_MODE_MAX + }; + SdfgiDirectLightShaderRD direct_light; + RID direct_light_shader; + RID direct_light_pipeline[DIRECT_LIGHT_MODE_MAX]; + + enum { + INTEGRATE_MODE_PROCESS, + INTEGRATE_MODE_STORE, + INTEGRATE_MODE_SCROLL, + INTEGRATE_MODE_SCROLL_STORE, + INTEGRATE_MODE_MAX + }; + struct IntegratePushConstant { + enum { + SKY_MODE_DISABLED, + SKY_MODE_COLOR, + SKY_MODE_SKY, + }; + + float grid_size[3]; + uint32_t max_cascades; + + uint32_t probe_axis_size; + uint32_t cascade; + uint32_t history_index; + uint32_t history_size; + + uint32_t ray_count; + float ray_bias; + int32_t image_size[2]; + + int32_t world_offset[3]; + uint32_t sky_mode; + + int32_t scroll[3]; + float sky_energy; + + float sky_color[3]; + float y_mult; + }; + + SdfgiIntegrateShaderRD integrate; + RID integrate_shader; + RID integrate_pipeline[INTEGRATE_MODE_MAX]; + + RID integrate_default_sky_uniform_set; + + } sdfgi_shader; + + void _sdfgi_erase(RenderBuffers *rb); + int _sdfgi_get_pending_region_data(RID p_render_buffers, int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const; + void _sdfgi_update_cascades(RID p_render_buffers); + + /* GI */ + + struct GI { + struct SDFGIData { + float grid_size[3]; + uint32_t max_cascades; + + uint32_t use_occlusion; + int32_t probe_axis_size; + float probe_to_uvw; + float normal_bias; + + float lightprobe_tex_pixel_size[3]; + float energy; + + float lightprobe_uv_offset[3]; + float y_mult; + + float occlusion_clamp[3]; + uint32_t pad3; + + float occlusion_renormalize[3]; + uint32_t pad4; + + float cascade_probe_size[3]; + uint32_t pad5; + + struct ProbeCascadeData { + float position[3]; //offset of (0,0,0) in world coordinates + float to_probe; // 1/bounds * grid_size + int32_t probe_world_offset[3]; + float to_cell; // 1/bounds * grid_size + }; + + ProbeCascadeData cascades[SDFGI::MAX_CASCADES]; + }; + + struct GIProbeData { + float xform[16]; + float bounds[3]; + float dynamic_range; + + float bias; + float normal_bias; + uint32_t blend_ambient; + uint32_t texture_slot; + + float anisotropy_strength; + float ao; + float ao_size; + uint32_t pad[1]; + }; + + struct PushConstant { + int32_t screen_size[2]; + float z_near; + float z_far; + + float proj_info[4]; + + uint32_t max_giprobes; + uint32_t high_quality_vct; + uint32_t use_sdfgi; + uint32_t orthogonal; + + float ao_color[3]; + uint32_t pad; + + float cam_rotation[12]; + }; + + RID sdfgi_ubo; + enum { + MODE_MAX = 1 + }; + + GiShaderRD shader; + RID shader_version; + RID pipelines[MODE_MAX]; + } gi; + bool screen_space_roughness_limiter = false; - float screen_space_roughness_limiter_curve = 1.0; + float screen_space_roughness_limiter_amount = 0.25; + float screen_space_roughness_limiter_limit = 0.18; mutable RID_Owner<RenderBuffers> render_buffers_owner; @@ -777,10 +1178,16 @@ private: void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas); void _render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection); + void _sdfgi_debug_draw(RID p_render_buffers, const CameraMatrix &p_projection, const Transform &p_transform); uint64_t scene_pass = 0; uint64_t shadow_atlas_realloc_tolerance_msec = 500; + struct SDFGICosineNeighbour { + uint32_t neighbour; + float weight; + }; + public: /* SHADOW ATLAS API */ @@ -818,6 +1225,15 @@ public: return Size2i(directional_shadow.size, directional_shadow.size); } + /* SDFGI UPDATE */ + + int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; } + virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position); + virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const; + virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const; + virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const; + virtual void sdfgi_update_probes(RID p_render_buffers, RID p_environment, const RID *p_directional_light_instances, uint32_t p_directional_light_count, const RID *p_positional_light_instances, uint32_t p_positional_light_count); + RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; } /* SKY API */ RID sky_create(); @@ -871,6 +1287,11 @@ public: float environment_get_ssao_ao_affect(RID p_env) const; float environment_get_ssao_light_affect(RID p_env) const; bool environment_is_ssr_enabled(RID p_env) const; + bool environment_is_sdfgi_enabled(RID p_env) const; + + virtual void environment_set_sdfgi(RID p_env, bool p_enable, RS::EnvironmentSDFGICascades p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias); + virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count); + virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames); void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality); RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const; @@ -894,6 +1315,7 @@ public: RID light_instance_create(RID p_light); void light_instance_set_transform(RID p_light_instance, const Transform &p_transform); + void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb); void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()); void light_instance_mark_visible(RID p_light_instance); @@ -1107,6 +1529,8 @@ public: bool gi_probe_needs_update(RID p_probe) const; void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects); + void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; } + _FORCE_INLINE_ uint32_t gi_probe_instance_get_slot(RID p_probe) { GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); return gi_probe->slot; @@ -1124,10 +1548,6 @@ public: GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); return gi_probe->texture; } - _FORCE_INLINE_ RID gi_probe_instance_get_aniso_texture(RID p_probe, int p_index) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - return gi_probe->anisotropy[p_index]; - } _FORCE_INLINE_ void gi_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) { GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance); @@ -1141,7 +1561,7 @@ public: return gi_probe->render_index; } - + /* _FORCE_INLINE_ void gi_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND(!g_probe); @@ -1154,18 +1574,27 @@ public: return g_probe->last_pass; } - - const Vector<RID> &gi_probe_get_slots() const; - _FORCE_INLINE_ bool gi_probe_is_anisotropic() const { - return gi_probe_use_anisotropy; - } - GIProbeQuality gi_probe_get_quality() const; - +*/ RID render_buffers_create(); void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa); RID render_buffers_get_ao_texture(RID p_render_buffers); RID render_buffers_get_back_buffer_texture(RID p_render_buffers); + RID render_buffers_get_gi_probe_buffer(RID p_render_buffers); + RID render_buffers_get_default_gi_probe_buffer(); + + uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const; + bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const; + RID render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const; + Vector3 render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const; + Vector3i render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const; + float render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const; + float render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const; + uint32_t render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const; + uint32_t render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const; + bool render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const; + float render_buffers_get_sdfgi_energy(RID p_render_buffers) const; + RID render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const; void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID *p_decal_cull_result, int p_decal_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); @@ -1173,6 +1602,9 @@ public: void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); + void render_sdfgi(RID p_render_buffers, int p_region, InstanceBase **p_cull_result, int p_cull_count); + void render_sdfgi_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const RID **p_positional_light_cull_result, const uint32_t *p_positional_light_cull_count); + virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; } @@ -1180,9 +1612,10 @@ public: return scene_pass; } - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve); + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit); virtual bool screen_space_roughness_limiter_is_active() const; - virtual float screen_space_roughness_limiter_get_curve() const; + virtual float screen_space_roughness_limiter_get_amount() const; + virtual float screen_space_roughness_limiter_get_limit() const; virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality); RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const; @@ -1221,6 +1654,8 @@ public: virtual void set_time(double p_time, double p_step); + void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir); + RasterizerSceneRD(RasterizerStorageRD *p_storage); ~RasterizerSceneRD(); }; diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index a5151d1ff8..8f3e2c25f9 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -3387,11 +3387,21 @@ void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_e light->instance_dependency.instance_notify_changed(true, false); } -void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) { +void RasterizerStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); - light->use_gi = p_enabled; + light->bake_mode = p_bake_mode; + + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->max_sdfgi_cascade = p_cascade; light->version++; light->instance_dependency.instance_notify_changed(true, false); @@ -3460,11 +3470,18 @@ RS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_ return light->directional_range_mode; } -bool RasterizerStorageRD::light_get_use_gi(RID p_light) { - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, false); +uint32_t RasterizerStorageRD::light_get_max_sdfgi_cascade(RID p_light) { + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->max_sdfgi_cascade; +} + +RS::LightBakeMode RasterizerStorageRD::light_get_bake_mode(RID p_light) { + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_BAKE_DISABLED); - return light->use_gi; + return light->bake_mode; } uint64_t RasterizerStorageRD::light_get_version(RID p_light) const { @@ -3517,25 +3534,25 @@ void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_in reflection_probe->intensity = p_intensity; } -void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) { +void RasterizerStorageRD::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); - reflection_probe->interior_ambient = p_ambient; + reflection_probe->ambient_mode = p_mode; } -void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) { +void RasterizerStorageRD::reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); - reflection_probe->interior_ambient_energy = p_energy; + reflection_probe->ambient_color = p_color; } -void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) { +void RasterizerStorageRD::reflection_probe_set_ambient_energy(RID p_probe, float p_energy) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); - reflection_probe->interior_ambient_probe_contrib = p_contrib; + reflection_probe->ambient_color_energy = p_energy; } void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) { @@ -3683,25 +3700,23 @@ bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const return reflection_probe->box_projection; } -Color RasterizerStorageRD::reflection_probe_get_interior_ambient(RID p_probe) const { +RS::ReflectionProbeAmbientMode RasterizerStorageRD::reflection_probe_get_ambient_mode(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Color()); - - return reflection_probe->interior_ambient; + ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_AMBIENT_DISABLED); + return reflection_probe->ambient_mode; } -float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const { +Color RasterizerStorageRD::reflection_probe_get_ambient_color(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); + ERR_FAIL_COND_V(!reflection_probe, Color()); - return reflection_probe->interior_ambient_energy; + return reflection_probe->ambient_color; } - -float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const { +float RasterizerStorageRD::reflection_probe_get_ambient_color_energy(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND_V(!reflection_probe, 0); - return reflection_probe->interior_ambient_probe_contrib; + return reflection_probe->ambient_color_energy; } RID RasterizerStorageRD::decal_create() { @@ -5878,6 +5893,20 @@ RasterizerStorageRD::RasterizerStorageRD() { } default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UINT; + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_2D_UINT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } } { //create default cubemap diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h index fe9377192e..b1146f1386 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h @@ -92,6 +92,7 @@ public: DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, DEFAULT_RD_TEXTURE_3D_WHITE, DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, + DEFAULT_RD_TEXTURE_2D_UINT, DEFAULT_RD_TEXTURE_MAX }; @@ -420,7 +421,8 @@ private: bool shadow = false; bool negative = false; bool reverse_cull = false; - bool use_gi = true; + RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC; + uint32_t max_sdfgi_cascade = 2; uint32_t cull_mask = 0xFFFFFFFF; RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; @@ -439,9 +441,9 @@ private: RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; int resolution = 256; float intensity = 1.0; - Color interior_ambient; - float interior_ambient_energy = 1.0; - float interior_ambient_probe_contrib = 0.0; + RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT; + Color ambient_color; + float ambient_color_energy = 1.0; float max_distance = 0; Vector3 extents = Vector3(1, 1, 1); Vector3 origin_offset; @@ -1041,7 +1043,8 @@ public: void light_set_negative(RID p_light, bool p_enable); void light_set_cull_mask(RID p_light, uint32_t p_mask); void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); - void light_set_use_gi(RID p_light, bool p_enabled); + void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode); + void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade); void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode); @@ -1118,7 +1121,8 @@ public: return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS]; } - bool light_get_use_gi(RID p_light); + RS::LightBakeMode light_get_bake_mode(RID p_light); + uint32_t light_get_max_sdfgi_cascade(RID p_light); uint64_t light_get_version(RID p_light) const; /* PROBE API */ @@ -1127,9 +1131,9 @@ public: void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode); void reflection_probe_set_intensity(RID p_probe, float p_intensity); - void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient); - void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy); - void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib); + void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode); + void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color); + void reflection_probe_set_ambient_energy(RID p_probe, float p_energy); void reflection_probe_set_max_distance(RID p_probe, float p_distance); void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents); void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset); @@ -1151,9 +1155,9 @@ public: float reflection_probe_get_intensity(RID p_probe) const; bool reflection_probe_is_interior(RID p_probe) const; bool reflection_probe_is_box_projection(RID p_probe) const; - Color reflection_probe_get_interior_ambient(RID p_probe) const; - float reflection_probe_get_interior_ambient_energy(RID p_probe) const; - float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const; + RS::ReflectionProbeAmbientMode reflection_probe_get_ambient_mode(RID p_probe) const; + Color reflection_probe_get_ambient_color(RID p_probe) const; + float reflection_probe_get_ambient_color_energy(RID p_probe) const; void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp index 79bb990649..1820c39c5a 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp @@ -399,6 +399,9 @@ void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const S if (i > 0) { header += ", "; } + if (fnode->arguments[i].is_const) { + header += "const "; + } if (fnode->arguments[i].type == SL::TYPE_STRUCT) { header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name); } else { diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/rasterizer_rd/shaders/SCsub index a454d144aa..67f4edc626 100644 --- a/servers/rendering/rasterizer_rd/shaders/SCsub +++ b/servers/rendering/rasterizer_rd/shaders/SCsub @@ -28,3 +28,10 @@ if "RD_GLSL" in env["BUILDERS"]: env.RD_GLSL("screen_space_reflection_scale.glsl") env.RD_GLSL("subsurface_scattering.glsl") env.RD_GLSL("specular_merge.glsl") + env.RD_GLSL("gi.glsl") + env.RD_GLSL("resolve.glsl") + env.RD_GLSL("sdfgi_preprocess.glsl") + env.RD_GLSL("sdfgi_integrate.glsl") + env.RD_GLSL("sdfgi_direct_light.glsl") + env.RD_GLSL("sdfgi_debug.glsl") + env.RD_GLSL("sdfgi_debug_probes.glsl") diff --git a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl index b1cfe1e91e..9751e13b4e 100644 --- a/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl +++ b/servers/rendering/rasterizer_rd/shaders/copy_to_fb.glsl @@ -47,16 +47,26 @@ layout(push_constant, binding = 1, std430) uniform Params { bool force_luminance; bool alpha_to_zero; - uint pad[2]; + bool srgb; + uint pad; } params; layout(location = 0) in vec2 uv_interp; layout(set = 0, binding = 0) uniform sampler2D source_color; - +#ifdef MODE_TWO_SOURCES +layout(set = 1, binding = 0) uniform sampler2D source_color2; +#endif layout(location = 0) out vec4 frag_color; +vec3 linear_to_srgb(vec3 color) { + //if going to srgb, clamp from 0 to 1. + color = clamp(color, vec3(0.0), vec3(1.0)); + const vec3 a = vec3(0.055f); + return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); +} + void main() { vec2 uv = uv_interp; @@ -89,11 +99,17 @@ void main() { } #endif vec4 color = textureLod(source_color, uv, 0.0); +#ifdef MODE_TWO_SOURCES + color += textureLod(source_color2, uv, 0.0); +#endif if (params.force_luminance) { color.rgb = vec3(max(max(color.r, color.g), color.b)); } if (params.alpha_to_zero) { color.rgb *= color.a; } + if (params.srgb) { + color.rgb = linear_to_srgb(color.rgb); + } frag_color = color; } diff --git a/servers/rendering/rasterizer_rd/shaders/gi.glsl b/servers/rendering/rasterizer_rd/shaders/gi.glsl new file mode 100644 index 0000000000..a1939f75ad --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/gi.glsl @@ -0,0 +1,663 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#define M_PI 3.141592 + +#define SDFGI_MAX_CASCADES 8 + +//set 0 for SDFGI and render buffers + +layout(set = 0, binding = 1) uniform texture3D sdf_cascades[SDFGI_MAX_CASCADES]; +layout(set = 0, binding = 2) uniform texture3D light_cascades[SDFGI_MAX_CASCADES]; +layout(set = 0, binding = 3) uniform texture3D aniso0_cascades[SDFGI_MAX_CASCADES]; +layout(set = 0, binding = 4) uniform texture3D aniso1_cascades[SDFGI_MAX_CASCADES]; +layout(set = 0, binding = 5) uniform texture3D occlusion_texture; + +layout(set = 0, binding = 6) uniform sampler linear_sampler; +layout(set = 0, binding = 7) uniform sampler linear_sampler_with_mipmaps; + +struct ProbeCascadeData { + vec3 position; + float to_probe; + ivec3 probe_world_offset; + float to_cell; // 1/bounds * grid_size +}; + +layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image2D ambient_buffer; +layout(rgba16f, set = 0, binding = 10) uniform restrict writeonly image2D reflection_buffer; + +layout(set = 0, binding = 11) uniform texture2DArray lightprobe_texture; + +layout(set = 0, binding = 12) uniform texture2D depth_buffer; +layout(set = 0, binding = 13) uniform texture2D normal_roughness_buffer; +layout(set = 0, binding = 14) uniform utexture2D giprobe_buffer; + +layout(set = 0, binding = 15, std140) uniform SDFGI { + vec3 grid_size; + uint max_cascades; + + bool use_occlusion; + int probe_axis_size; + float probe_to_uvw; + float normal_bias; + + vec3 lightprobe_tex_pixel_size; + float energy; + + vec3 lightprobe_uv_offset; + float y_mult; + + vec3 occlusion_clamp; + uint pad3; + + vec3 occlusion_renormalize; + uint pad4; + + vec3 cascade_probe_size; + uint pad5; + + ProbeCascadeData cascades[SDFGI_MAX_CASCADES]; +} +sdfgi; + +#define MAX_GI_PROBES 8 + +struct GIProbeData { + mat4 xform; + vec3 bounds; + float dynamic_range; + + float bias; + float normal_bias; + bool blend_ambient; + uint texture_slot; + + float anisotropy_strength; + float ambient_occlusion; + float ambient_occlusion_size; + uint pad2; +}; + +layout(set = 0, binding = 16, std140) uniform GIProbes { + GIProbeData data[MAX_GI_PROBES]; +} +gi_probes; + +layout(set = 0, binding = 17) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; + +layout(push_constant, binding = 0, std430) uniform Params { + ivec2 screen_size; + float z_near; + float z_far; + + vec4 proj_info; + + uint max_giprobes; + bool high_quality_vct; + bool use_sdfgi; + bool orthogonal; + + vec3 ao_color; + uint pad; + + mat3x4 cam_rotation; +} +params; + +vec2 octahedron_wrap(vec2 v) { + vec2 signVal; + signVal.x = v.x >= 0.0 ? 1.0 : -1.0; + signVal.y = v.y >= 0.0 ? 1.0 : -1.0; + return (1.0 - abs(v.yx)) * signVal; +} + +vec2 octahedron_encode(vec3 n) { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; +} + +vec4 blend_color(vec4 src, vec4 dst) { + vec4 res; + float sa = 1.0 - src.a; + res.a = dst.a * sa + src.a; + if (res.a == 0.0) { + res.rgb = vec3(0); + } else { + res.rgb = (dst.rgb * dst.a * sa + src.rgb * src.a) / res.a; + } + return res; +} + +vec3 reconstruct_position(ivec2 screen_pos) { + vec3 pos; + pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; + + pos.z = pos.z * 2.0 - 1.0; + if (params.orthogonal) { + pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near)); + } + pos.z = -pos.z; + + pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; + if (!params.orthogonal) { + pos.xy *= pos.z; + } + + return pos; +} + +void sdfgi_probe_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) { + cascade_pos += cam_normal * sdfgi.normal_bias; + + vec3 base_pos = floor(cascade_pos); + //cascade_pos += mix(vec3(0.0),vec3(0.01),lessThan(abs(cascade_pos-base_pos),vec3(0.01))) * cam_normal; + ivec3 probe_base_pos = ivec3(base_pos); + + vec4 diffuse_accum = vec4(0.0); + vec3 specular_accum; + + ivec3 tex_pos = ivec3(probe_base_pos.xy, int(cascade)); + tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size; + tex_pos.xy = tex_pos.xy * (SDFGI_OCT_SIZE + 2) + ivec2(1); + + vec3 diffuse_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size; + + vec3 specular_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_specular_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size; + + specular_accum = vec3(0.0); + + vec4 light_accum = vec4(0.0); + float weight_accum = 0.0; + + for (uint j = 0; j < 8; j++) { + ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1); + ivec3 probe_posi = probe_base_pos; + probe_posi += offset; + + // Compute weight + + vec3 probe_pos = vec3(probe_posi); + vec3 probe_to_pos = cascade_pos - probe_pos; + vec3 probe_dir = normalize(-probe_to_pos); + + vec3 trilinear = vec3(1.0) - abs(probe_to_pos); + float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(cam_normal, probe_dir)); + + // Compute lightprobe occlusion + + if (sdfgi.use_occlusion) { + ivec3 occ_indexv = abs((sdfgi.cascades[cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4); + vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3))); + + vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw; + occ_pos.z += float(cascade); + if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures + occ_pos.x += 1.0; + } + + occ_pos *= sdfgi.occlusion_renormalize; + float occlusion = dot(textureLod(sampler3D(occlusion_texture, linear_sampler), occ_pos, 0.0), occ_mask); + + weight *= max(occlusion, 0.01); + } + + // Compute lightprobe texture position + + vec3 diffuse; + vec3 pos_uvw = diffuse_posf; + pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy; + pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z; + diffuse = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb; + + diffuse_accum += vec4(diffuse * weight, weight); + + { + vec3 specular = vec3(0.0); + vec3 pos_uvw = specular_posf; + pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy; + pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z; + if (roughness < 0.99) { + specular = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw + vec3(0, 0, float(sdfgi.max_cascades)), 0.0).rgb; + } + if (roughness > 0.2) { + specular = mix(specular, textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb, (roughness - 0.2) * 1.25); + } + + specular_accum += specular * weight; + } + } + + if (diffuse_accum.a > 0.0) { + diffuse_accum.rgb /= diffuse_accum.a; + } + + diffuse_light = diffuse_accum.rgb; + + if (diffuse_accum.a > 0.0) { + specular_accum /= diffuse_accum.a; + } + + specular_light = specular_accum; +} + +void sdfgi_process(vec3 vertex, vec3 normal, vec3 reflection, float roughness, out vec4 ambient_light, out vec4 reflection_light) { + //make vertex orientation the world one, but still align to camera + vertex.y *= sdfgi.y_mult; + normal.y *= sdfgi.y_mult; + reflection.y *= sdfgi.y_mult; + + //renormalize + normal = normalize(normal); + reflection = normalize(reflection); + + vec3 cam_pos = vertex; + vec3 cam_normal = normal; + + vec4 light_accum = vec4(0.0); + float weight_accum = 0.0; + + vec4 light_blend_accum = vec4(0.0); + float weight_blend_accum = 0.0; + + float blend = -1.0; + + // helper constants, compute once + + uint cascade = 0xFFFFFFFF; + vec3 cascade_pos; + vec3 cascade_normal; + + for (uint i = 0; i < sdfgi.max_cascades; i++) { + cascade_pos = (cam_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe; + + if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) { + continue; //skip cascade + } + + cascade = i; + break; + } + + if (cascade < SDFGI_MAX_CASCADES) { + ambient_light = vec4(0, 0, 0, 1); + reflection_light = vec4(0, 0, 0, 1); + + float blend; + vec3 diffuse, specular; + sdfgi_probe_process(cascade, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse, specular); + + { + //process blend + float blend_from = (float(sdfgi.probe_axis_size - 1) / 2.0) - 2.5; + float blend_to = blend_from + 2.0; + + vec3 inner_pos = cam_pos * sdfgi.cascades[cascade].to_probe; + + float len = length(inner_pos); + + inner_pos = abs(normalize(inner_pos)); + len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z)); + + if (len >= blend_from) { + blend = smoothstep(blend_from, blend_to, len); + } else { + blend = 0.0; + } + } + + if (blend > 0.0) { + //blend + if (cascade == sdfgi.max_cascades - 1) { + ambient_light.a = 1.0 - blend; + reflection_light.a = 1.0 - blend; + + } else { + vec3 diffuse2, specular2; + cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe; + sdfgi_probe_process(cascade + 1, cascade_pos, cam_pos, cam_normal, reflection, roughness, diffuse2, specular2); + diffuse = mix(diffuse, diffuse2, blend); + specular = mix(specular, specular2, blend); + } + } + + ambient_light.rgb = diffuse; +#if 1 + if (roughness < 0.2) { + vec3 pos_to_uvw = 1.0 / sdfgi.grid_size; + vec4 light_accum = vec4(0.0); + + float blend_size = (sdfgi.grid_size.x / float(sdfgi.probe_axis_size - 1)) * 0.5; + + float radius_sizes[SDFGI_MAX_CASCADES]; + cascade = 0xFFFF; + + float base_distance = length(cam_pos); + for (uint i = 0; i < sdfgi.max_cascades; i++) { + radius_sizes[i] = (1.0 / sdfgi.cascades[i].to_cell) * (sdfgi.grid_size.x * 0.5 - blend_size); + if (cascade == 0xFFFF && base_distance < radius_sizes[i]) { + cascade = i; + } + } + + cascade = min(cascade, sdfgi.max_cascades - 1); + + float max_distance = radius_sizes[sdfgi.max_cascades - 1]; + vec3 ray_pos = cam_pos; + vec3 ray_dir = reflection; + + { + float prev_radius = cascade > 0 ? radius_sizes[cascade - 1] : 0.0; + float base_blend = (base_distance - prev_radius) / (radius_sizes[cascade] - prev_radius); + float bias = (1.0 + base_blend) * 1.1; + vec3 abs_ray_dir = abs(ray_dir); + //ray_pos += ray_dir * (bias / sdfgi.cascades[cascade].to_cell); //bias to avoid self occlusion + ray_pos += (ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) + cam_normal * 1.4) * bias / sdfgi.cascades[cascade].to_cell; + } + + float softness = 0.2 + min(1.0, roughness * 5.0) * 4.0; //approximation to roughness so it does not seem like a hard fade + while (length(ray_pos) < max_distance) { + for (uint i = 0; i < sdfgi.max_cascades; i++) { + if (i >= cascade && length(ray_pos) < radius_sizes[i]) { + cascade = max(i, cascade); //never go down + + vec3 pos = ray_pos - sdfgi.cascades[i].position; + pos *= sdfgi.cascades[i].to_cell * pos_to_uvw; + + float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), pos).r * 255.0 - 1.1; + + vec4 hit_light = vec4(0.0); + if (distance < softness) { + hit_light.rgb = texture(sampler3D(light_cascades[i], linear_sampler), pos).rgb; + hit_light.rgb *= 0.5; //approximation given value read is actually meant for anisotropy + hit_light.a = clamp(1.0 - (distance / softness), 0.0, 1.0); + hit_light.rgb *= hit_light.a; + } + + distance /= sdfgi.cascades[i].to_cell; + + if (i < (sdfgi.max_cascades - 1)) { + pos = ray_pos - sdfgi.cascades[i + 1].position; + pos *= sdfgi.cascades[i + 1].to_cell * pos_to_uvw; + + float distance2 = texture(sampler3D(sdf_cascades[i + 1], linear_sampler), pos).r * 255.0 - 1.1; + + vec4 hit_light2 = vec4(0.0); + if (distance2 < softness) { + hit_light2.rgb = texture(sampler3D(light_cascades[i + 1], linear_sampler), pos).rgb; + hit_light2.rgb *= 0.5; //approximation given value read is actually meant for anisotropy + hit_light2.a = clamp(1.0 - (distance2 / softness), 0.0, 1.0); + hit_light2.rgb *= hit_light2.a; + } + + float prev_radius = i == 0 ? 0.0 : radius_sizes[i - 1]; + float blend = clamp((length(ray_pos) - prev_radius) / (radius_sizes[i] - prev_radius), 0.0, 1.0); + + distance2 /= sdfgi.cascades[i + 1].to_cell; + + hit_light = mix(hit_light, hit_light2, blend); + distance = mix(distance, distance2, blend); + } + + light_accum += hit_light; + ray_pos += ray_dir * distance; + break; + } + } + + if (light_accum.a > 0.99) { + break; + } + } + + vec3 light = light_accum.rgb / max(light_accum.a, 0.00001); + float alpha = min(1.0, light_accum.a); + + float b = min(1.0, roughness * 5.0); + + float sa = 1.0 - b; + + reflection_light.a = alpha * sa + b; + if (reflection_light.a == 0) { + specular = vec3(0.0); + } else { + specular = (light * alpha * sa + specular * b) / reflection_light.a; + } + } + +#endif + + reflection_light.rgb = specular; + + ambient_light.rgb *= sdfgi.energy; + reflection_light.rgb *= sdfgi.energy; + } else { + ambient_light = vec4(0); + reflection_light = vec4(0); + } +} + +//standard voxel cone trace +vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { + float dist = p_bias; + vec4 color = vec4(0.0); + + while (dist < max_distance && color.a < 0.95) { + float diameter = max(1.0, 2.0 * tan_half_angle * dist); + vec3 uvw_pos = (pos + dist * direction) * cell_size; + float half_diameter = diameter * 0.5; + //check if outside, then break + if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) { + break; + } + vec4 scolor = textureLod(sampler3D(probe, linear_sampler_with_mipmaps), uvw_pos, log2(diameter)); + float a = (1.0 - color.a); + color += a * scolor; + dist += half_diameter; + } + + return color; +} + +vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float max_distance, float p_bias) { + float dist = p_bias; + vec4 color = vec4(0.0); + float radius = max(0.5, dist); + float lod_level = log2(radius * 2.0); + + while (dist < max_distance && color.a < 0.95) { + vec3 uvw_pos = (pos + dist * direction) * cell_size; + + //check if outside, then break + if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) { + break; + } + vec4 scolor = textureLod(sampler3D(probe, linear_sampler_with_mipmaps), uvw_pos, lod_level); + lod_level += 1.0; + + float a = (1.0 - color.a); + scolor *= a; + color += scolor; + dist += radius; + radius = max(0.5, dist); + } + return color; +} + +void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, inout vec4 out_spec, inout vec4 out_diff, inout float out_blend) { + position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz; + ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz); + normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz); + + position += normal * gi_probes.data[index].normal_bias; + + //this causes corrupted pixels, i have no idea why.. + if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) { + return; + } + + mat3 dir_xform = mat3(gi_probes.data[index].xform) * normal_xform; + + vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0); + float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0); + //float blend=1.0; + + float max_distance = length(gi_probes.data[index].bounds); + vec3 cell_size = 1.0 / gi_probes.data[index].bounds; + + //irradiance + + vec4 light = vec4(0.0); + + if (params.high_quality_vct) { + const uint cone_dir_count = 6; + vec3 cone_dirs[cone_dir_count] = vec3[]( + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5)); + + float cone_weights[cone_dir_count] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); + float cone_angle_tan = 0.577; + + for (uint i = 0; i < cone_dir_count; i++) { + vec3 dir = normalize(dir_xform * cone_dirs[i]); + light += cone_weights[i] * voxel_cone_trace(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); + } + } else { + const uint cone_dir_count = 4; + vec3 cone_dirs[cone_dir_count] = vec3[]( + vec3(0.707107, 0.0, 0.707107), + vec3(0.0, 0.707107, 0.707107), + vec3(-0.707107, 0.0, 0.707107), + vec3(0.0, -0.707107, 0.707107)); + + float cone_weights[cone_dir_count] = float[](0.25, 0.25, 0.25, 0.25); + for (int i = 0; i < cone_dir_count; i++) { + vec3 dir = normalize(dir_xform * cone_dirs[i]); + light += cone_weights[i] * voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, max_distance, gi_probes.data[index].bias); + } + } + + if (gi_probes.data[index].ambient_occlusion > 0.001) { + float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0; + + float taps, blend; + blend = modf(size, taps); + float ao = 0.0; + for (float i = 1.0; i <= taps; i++) { + vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size; + ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, i - 1.0).a * i; + } + + if (blend > 0.001) { + vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size; + ao += textureLod(sampler3D(gi_probe_textures[index], linear_sampler_with_mipmaps), ofs, taps).a * (taps + 1.0) * blend; + } + + ao = 1.0 - min(1.0, ao); + + light.rgb = mix(params.ao_color, light.rgb, mix(1.0, ao, gi_probes.data[index].ambient_occlusion)); + } + + light.rgb *= gi_probes.data[index].dynamic_range; + if (!gi_probes.data[index].blend_ambient) { + light.a = 1.0; + } + + out_diff += light * blend; + + //radiance + vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias); + irr_light.rgb *= gi_probes.data[index].dynamic_range; + if (!gi_probes.data[index].blend_ambient) { + irr_light.a = 1.0; + } + + out_spec += irr_light * blend; + + out_blend += blend; +} + +vec4 fetch_normal_and_roughness(ivec2 pos) { + vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0); + + normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0); + return normal_roughness; +} + +void main() { + // Pixel being shaded + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing + return; + } + + vec3 vertex = reconstruct_position(pos); + vertex.y = -vertex.y; + + vec4 normal_roughness = fetch_normal_and_roughness(pos); + vec3 normal = normal_roughness.xyz; + + vec4 ambient_light = vec4(0.0), reflection_light = vec4(0.0); + + if (normal.length() > 0.5) { + //valid normal, can do GI + float roughness = normal_roughness.w; + + vertex = mat3(params.cam_rotation) * vertex; + normal = normalize(mat3(params.cam_rotation) * normal); + + vec3 reflection = normalize(reflect(normalize(vertex), normal)); + + if (params.use_sdfgi) { + sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light); + } + + if (params.max_giprobes > 0) { + uvec2 giprobe_tex = texelFetch(usampler2D(giprobe_buffer, linear_sampler), pos, 0).rg; + roughness *= roughness; + //find arbitrary tangent and bitangent, then build a matrix + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, normal)); + vec3 bitangent = normalize(cross(tangent, normal)); + mat3 normal_mat = mat3(tangent, bitangent, normal); + + vec4 amb_accum = vec4(0.0); + vec4 spec_accum = vec4(0.0); + float blend_accum = 0.0; + + for (uint i = 0; i < params.max_giprobes; i++) { + if (any(equal(uvec2(i), giprobe_tex))) { + gi_probe_compute(i, vertex, normal, reflection, normal_mat, roughness, spec_accum, amb_accum, blend_accum); + } + } + if (blend_accum > 0.0) { + amb_accum /= blend_accum; + spec_accum /= blend_accum; + } + + if (params.use_sdfgi) { + reflection_light = blend_color(spec_accum, reflection_light); + ambient_light = blend_color(amb_accum, ambient_light); + } else { + reflection_light = spec_accum; + ambient_light = amb_accum; + } + } + } + + imageStore(ambient_buffer, pos, ambient_light); + imageStore(reflection_buffer, pos, reflection_light); +} diff --git a/servers/rendering/rasterizer_rd/shaders/resolve.glsl b/servers/rendering/rasterizer_rd/shaders/resolve.glsl new file mode 100644 index 0000000000..9429a66dc9 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/resolve.glsl @@ -0,0 +1,110 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#ifdef MODE_RESOLVE_GI +layout(set = 0, binding = 0) uniform sampler2DMS source_depth; +layout(set = 0, binding = 1) uniform sampler2DMS source_normal_roughness; + +layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_depth; +layout(rgba8, set = 1, binding = 1) uniform restrict writeonly image2D dest_normal_roughness; + +#ifdef GIPROBE_RESOLVE +layout(set = 2, binding = 0) uniform usampler2DMS source_giprobe; +layout(rg8ui, set = 3, binding = 0) uniform restrict writeonly uimage2D dest_giprobe; +#endif + +#endif + +layout(push_constant, binding = 16, std430) uniform Params { + ivec2 screen_size; + int sample_count; + uint pad; +} +params; + +void main() { + // Pixel being shaded + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing + return; + } + +#ifdef MODE_RESOLVE_GI + + float best_depth = 1e20; + vec4 best_normal_roughness = vec4(0.0); +#ifdef GIPROBE_RESOLVE + uvec2 best_giprobe; +#endif + +#if 0 + + for(int i=0;i<params.sample_count;i++) { + float depth = texelFetch(source_depth,pos,i).r; + if (depth < best_depth) { //use the depth closest to camera + best_depth = depth; + best_normal_roughness = texelFetch(source_normal_roughness,pos,i); + +#ifdef GIPROBE_RESOLVE + best_giprobe = texelFetch(source_giprobe,pos,i).rg; +#endif + } + } + +#else + + float depths[16]; + int depth_indices[16]; + int depth_amount[16]; + int depth_count = 0; + + for (int i = 0; i < params.sample_count; i++) { + float depth = texelFetch(source_depth, pos, i).r; + int depth_index = -1; + for (int j = 0; j < depth_count; j++) { + if (abs(depths[j] - depth) < 0.000001) { + depth_index = j; + break; + } + } + + if (depth_index == -1) { + depths[depth_count] = depth; + depth_indices[depth_count] = i; + depth_amount[depth_count] = 1; + depth_count += 1; + } else { + depth_amount[depth_index] += 1; + } + } + + int depth_least = 0xFFFF; + int best_index = 0; + for (int j = 0; j < depth_count; j++) { + if (depth_amount[j] < depth_least) { + best_index = depth_indices[j]; + depth_least = depth_amount[j]; + } + } + + best_depth = texelFetch(source_depth, pos, best_index).r; + best_normal_roughness = texelFetch(source_normal_roughness, pos, best_index); +#ifdef GIPROBE_RESOLVE + best_giprobe = texelFetch(source_giprobe, pos, best_index).rg; +#endif + +#endif + + imageStore(dest_depth, pos, vec4(best_depth)); + imageStore(dest_normal_roughness, pos, vec4(best_normal_roughness)); +#ifdef GIPROBE_RESOLVE + imageStore(dest_giprobe, pos, uvec4(best_giprobe, 0, 0)); +#endif + +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl index 9f42b0f814..d6a56b2543 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl @@ -258,7 +258,6 @@ VERTEX_SHADER_CODE } } #endif - #ifdef MODE_RENDER_MATERIAL if (scene_data.material_uv2_mode) { gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0; @@ -341,11 +340,13 @@ layout(location = 4) out float depth_output_buffer; #endif -#ifdef MODE_RENDER_NORMAL -layout(location = 0) out vec4 normal_output_buffer; -#ifdef MODE_RENDER_ROUGHNESS -layout(location = 1) out float roughness_output_buffer; -#endif //MODE_RENDER_ROUGHNESS +#ifdef MODE_RENDER_NORMAL_ROUGHNESS +layout(location = 0) out vec4 normal_roughness_output_buffer; + +#ifdef MODE_RENDER_GIPROBE +layout(location = 1) out uvec2 giprobe_buffer; +#endif + #endif //MODE_RENDER_NORMAL #else // RENDER DEPTH @@ -1321,37 +1322,39 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes reflection_accum += reflection; } -#if !defined(USE_LIGHTMAP) && !defined(USE_VOXEL_CONE_TRACING) - if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox + switch (reflections.data[ref_index].ambient_mode) { + case REFLECTION_AMBIENT_DISABLED: { + //do nothing + } break; + case REFLECTION_AMBIENT_ENVIRONMENT: { + //do nothing + vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz; - vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz; + vec4 ambient_out; - vec4 ambient_out; - - ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb; - - ambient_out.a = blend; - ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a); - if (reflections.data[ref_index].params.z < 0.5) { - ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); - } + ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb; + ambient_out.a = blend; + if (reflections.data[ref_index].params.z < 0.5) { //interior + ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); + } - ambient_out.rgb *= ambient_out.a; - ambient_accum += ambient_out; - } else { - vec4 ambient_out; - ambient_out.a = blend; - ambient_out.rgb = reflections.data[ref_index].ambient.rgb; - if (reflections.data[ref_index].params.z < 0.5) { - ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); - } - ambient_out.rgb *= ambient_out.a; - ambient_accum += ambient_out; + ambient_out.rgb *= ambient_out.a; + ambient_accum += ambient_out; + } break; + case REFLECTION_AMBIENT_COLOR: { + vec4 ambient_out; + ambient_out.a = blend; + ambient_out.rgb = reflections.data[ref_index].ambient; + if (reflections.data[ref_index].params.z < 0.5) { + ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); + } + ambient_out.rgb *= ambient_out.a; + ambient_accum += ambient_out; + } break; } -#endif //USE_LIGHTMAP or VCT } -#ifdef USE_VOXEL_CONE_TRACING +#ifdef USE_FORWARD_GI //standard voxel cone trace vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { @@ -1375,42 +1378,6 @@ vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, return color; } -#ifndef GI_PROBE_HIGH_QUALITY -//faster version for 45 degrees - -#ifdef GI_PROBE_USE_ANISOTROPY - -vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { - float dist = p_bias; - vec4 color = vec4(0.0); - float radius = max(0.5, tan_half_angle * dist); - float lod_level = log2(radius * 2.0); - - while (dist < max_distance && color.a < 0.95) { - vec3 uvw_pos = (pos + dist * direction) * cell_size; - //check if outside, then break - if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) { - break; - } - - vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level); - vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb; - vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb; - - scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0)); - lod_level += 1.0; - - float a = (1.0 - color.a); - scolor *= a; - color += scolor; - dist += radius; - radius = max(0.5, tan_half_angle * dist); - } - - return color; -} -#else - vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { float dist = p_bias; vec4 color = vec4(0.0); @@ -1437,41 +1404,6 @@ vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 return color; } -#endif - -#elif defined(GI_PROBE_USE_ANISOTROPY) - -//standard voxel cone trace -vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { - float dist = p_bias; - vec4 color = vec4(0.0); - - while (dist < max_distance && color.a < 0.95) { - float diameter = max(1.0, 2.0 * tan_half_angle * dist); - vec3 uvw_pos = (pos + dist * direction) * cell_size; - float half_diameter = diameter * 0.5; - //check if outside, then break - if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) { - break; - } - float log2_diameter = log2(diameter); - vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter); - vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb; - vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb; - - scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0)); - - float a = (1.0 - color.a); - scolor *= a; - color += scolor; - dist += half_diameter; - } - - return color; -} - -#endif - void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) { position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz; ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz); @@ -1493,31 +1425,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 //radiance -#ifdef GI_PROBE_HIGH_QUALITY - -#define MAX_CONE_DIRS 6 - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5)); - - float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); - float cone_angle_tan = 0.577; - -#elif defined(GI_PROBE_LOW_QUALITY) - -#define MAX_CONE_DIRS 1 - - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.0, 0.0, 1.0)); - - float cone_weights[MAX_CONE_DIRS] = float[](1.0); - float cone_angle_tan = 4; //~76 degrees -#else // MEDIUM QUALITY - #define MAX_CONE_DIRS 4 vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( @@ -1529,31 +1436,13 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); float cone_angle_tan = 0.98269; -#endif vec3 light = vec3(0.0); for (int i = 0; i < MAX_CONE_DIRS; i++) { vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz); -#if defined(GI_PROBE_HIGH_QUALITY) || defined(GI_PROBE_LOW_QUALITY) - -#ifdef GI_PROBE_USE_ANISOTROPY - vec4 cone_light = voxel_cone_trace_anisotropic(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); -#else - - vec4 cone_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); - -#endif // GI_PROBE_USE_ANISOTROPY - -#else - -#ifdef GI_PROBE_USE_ANISOTROPY - vec4 cone_light = voxel_cone_trace_anisotropic_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); -#else - vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); -#endif // GI_PROBE_USE_ANISOTROPY + vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); -#endif if (gi_probes.data[index].blend_ambient) { cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95)); } @@ -1562,33 +1451,10 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 } light *= gi_probes.data[index].dynamic_range; - - if (gi_probes.data[index].ambient_occlusion > 0.001) { - float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0; - - float taps, blend; - blend = modf(size, taps); - float ao = 0.0; - for (float i = 1.0; i <= taps; i++) { - vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size; - ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, i - 1.0).a * i; - } - - if (blend > 0.001) { - vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size; - ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, taps).a * (taps + 1.0) * blend; - } - - ao = 1.0 - min(1.0, ao); - - light = mix(scene_data.ao_color.rgb, light, mix(1.0, ao, gi_probes.data[index].ambient_occlusion)); - } - out_diff += vec4(light * blend, blend); //irradiance -#ifndef GI_PROBE_LOW_QUALITY - vec4 irr_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias); + vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias); if (gi_probes.data[index].blend_ambient) { irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95)); } @@ -1596,10 +1462,142 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 //irr_light=vec3(0.0); out_spec += vec4(irr_light.rgb * blend, blend); -#endif } -#endif //USE_VOXEL_CONE_TRACING +#endif //USE_FORWARD_GI + +vec2 octahedron_wrap(vec2 v) { + vec2 signVal; + signVal.x = v.x >= 0.0 ? 1.0 : -1.0; + signVal.y = v.y >= 0.0 ? 1.0 : -1.0; + return (1.0 - abs(v.yx)) * signVal; +} + +vec2 octahedron_encode(vec3 n) { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; +} + +void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, bool use_specular, float roughness, out vec3 diffuse_light, out vec3 specular_light, out float blend) { + cascade_pos += cam_normal * sdfgi.normal_bias; + + vec3 base_pos = floor(cascade_pos); + //cascade_pos += mix(vec3(0.0),vec3(0.01),lessThan(abs(cascade_pos-base_pos),vec3(0.01))) * cam_normal; + ivec3 probe_base_pos = ivec3(base_pos); + + vec4 diffuse_accum = vec4(0.0); + vec3 specular_accum; + + ivec3 tex_pos = ivec3(probe_base_pos.xy, int(cascade)); + tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size; + tex_pos.xy = tex_pos.xy * (SDFGI_OCT_SIZE + 2) + ivec2(1); + + vec3 diffuse_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size; + + vec3 specular_posf; + + if (use_specular) { + specular_accum = vec3(0.0); + specular_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_specular_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size; + } + + vec4 light_accum = vec4(0.0); + float weight_accum = 0.0; + + for (uint j = 0; j < 8; j++) { + ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1); + ivec3 probe_posi = probe_base_pos; + probe_posi += offset; + + // Compute weight + + vec3 probe_pos = vec3(probe_posi); + vec3 probe_to_pos = cascade_pos - probe_pos; + vec3 probe_dir = normalize(-probe_to_pos); + + vec3 trilinear = vec3(1.0) - abs(probe_to_pos); + float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(cam_normal, probe_dir)); + + // Compute lightprobe occlusion + + if (sdfgi.use_occlusion) { + ivec3 occ_indexv = abs((sdfgi.cascades[cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4); + vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3))); + + vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw; + occ_pos.z += float(cascade); + if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures + occ_pos.x += 1.0; + } + + occ_pos *= sdfgi.occlusion_renormalize; + float occlusion = dot(textureLod(sampler3D(sdfgi_occlusion_cascades, material_samplers[SAMPLER_LINEAR_CLAMP]), occ_pos, 0.0), occ_mask); + + weight *= max(occlusion, 0.01); + } + + // Compute lightprobe texture position + + vec3 diffuse; + vec3 pos_uvw = diffuse_posf; + pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy; + pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z; + diffuse = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb; + + diffuse_accum += vec4(diffuse * weight, weight); + + if (use_specular) { + vec3 specular = vec3(0.0); + vec3 pos_uvw = specular_posf; + pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy; + pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z; + if (roughness < 0.99) { + specular = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw + vec3(0, 0, float(sdfgi.max_cascades)), 0.0).rgb; + } + if (roughness > 0.5) { + specular = mix(specular, textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb, (roughness - 0.5) * 2.0); + } + + specular_accum += specular * weight; + } + } + + if (diffuse_accum.a > 0.0) { + diffuse_accum.rgb /= diffuse_accum.a; + } + + diffuse_light = diffuse_accum.rgb; + + if (use_specular) { + if (diffuse_accum.a > 0.0) { + specular_accum /= diffuse_accum.a; + } + + specular_light = specular_accum; + } + + { + //process blend + float blend_from = (float(sdfgi.probe_axis_size - 1) / 2.0) - 2.5; + float blend_to = blend_from + 2.0; + + vec3 inner_pos = cam_pos * sdfgi.cascades[cascade].to_probe; + + float len = length(inner_pos); + + inner_pos = abs(normalize(inner_pos)); + len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z)); + + if (len >= blend_from) { + blend = smoothstep(blend_from, blend_to, len); + } else { + blend = 0.0; + } + } +} #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) @@ -1812,6 +1810,15 @@ FRAGMENT_SHADER_CODE #endif //not render depth /////////////////////// LIGHTING ////////////////////////////// + if (scene_data.roughness_limiter_enabled) { + //http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf + float roughness2 = roughness * roughness; + vec3 dndu = dFdx(normal), dndv = dFdx(normal); + float variance = scene_data.roughness_limiter_amount * (dot(dndu, dndu) + dot(dndv, dndv)); + float kernelRoughness2 = min(2.0 * variance, scene_data.roughness_limiter_limit); //limit effect + float filteredRoughness2 = min(1.0, roughness2 + kernelRoughness2); + roughness = sqrt(filteredRoughness2); + } //apply energy conservation vec3 specular_light = vec3(0.0, 0.0, 0.0); @@ -1820,11 +1827,6 @@ FRAGMENT_SHADER_CODE #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - if (scene_data.roughness_limiter_enabled) { - float limit = texelFetch(sampler2D(roughness_buffer, material_samplers[SAMPLER_NEAREST_CLAMP]), ivec2(gl_FragCoord.xy), 0).r; - roughness = max(roughness, limit); - } - if (scene_data.use_reflection_cubemap) { vec3 ref_vec = reflect(-view, normal); ref_vec = scene_data.radiance_inverse_xform * ref_vec; @@ -1871,7 +1873,6 @@ FRAGMENT_SHADER_CODE #endif #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - //gi probes #ifdef USE_LIGHTMAP @@ -1928,10 +1929,80 @@ FRAGMENT_SHADER_CODE ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb; } } -#endif - //lightmap capture +#elif defined(USE_FORWARD_GI) + + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture + + //make vertex orientation the world one, but still align to camera + vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex; + vec3 cam_normal = mat3(scene_data.camera_matrix) * normal; + vec3 cam_reflection = mat3(scene_data.camera_matrix) * reflect(-view, normal); + + //apply y-mult + cam_pos.y *= sdfgi.y_mult; + cam_normal.y *= sdfgi.y_mult; + cam_normal = normalize(cam_normal); + cam_reflection.y *= sdfgi.y_mult; + cam_normal = normalize(cam_normal); + cam_reflection = normalize(cam_reflection); + + vec4 light_accum = vec4(0.0); + float weight_accum = 0.0; + + vec4 light_blend_accum = vec4(0.0); + float weight_blend_accum = 0.0; + + float blend = -1.0; + + // helper constants, compute once + + uint cascade = 0xFFFFFFFF; + vec3 cascade_pos; + vec3 cascade_normal; + + for (uint i = 0; i < sdfgi.max_cascades; i++) { + cascade_pos = (cam_pos - sdfgi.cascades[i].position) * sdfgi.cascades[i].to_probe; + + if (any(lessThan(cascade_pos, vec3(0.0))) || any(greaterThanEqual(cascade_pos, sdfgi.cascade_probe_size))) { + continue; //skip cascade + } + + cascade = i; + break; + } + + if (cascade < SDFGI_MAX_CASCADES) { + bool use_specular = true; + float blend; + vec3 diffuse, specular; + sdfgi_process(cascade, cascade_pos, cam_pos, cam_normal, cam_reflection, use_specular, roughness, diffuse, specular, blend); + + if (blend > 0.0) { + //blend + if (cascade == sdfgi.max_cascades - 1) { + diffuse = mix(diffuse, ambient_light, blend); + if (use_specular) { + specular = mix(specular, specular_light, blend); + } + } else { + vec3 diffuse2, specular2; + float blend2; + cascade_pos = (cam_pos - sdfgi.cascades[cascade + 1].position) * sdfgi.cascades[cascade + 1].to_probe; + sdfgi_process(cascade + 1, cascade_pos, cam_pos, cam_normal, cam_reflection, use_specular, roughness, diffuse2, specular2, blend2); + diffuse = mix(diffuse, diffuse2, blend); + if (use_specular) { + specular = mix(specular, specular2, blend); + } + } + } + + ambient_light = diffuse; + if (use_specular) { + specular_light = specular; + } + } + } -#ifdef USE_VOXEL_CONE_TRACING if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; @@ -1963,6 +2034,56 @@ FRAGMENT_SHADER_CODE specular_light = spec_accum.rgb; ambient_light = amb_accum.rgb; } +#else + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers + + ivec2 coord; + + if (scene_data.gi_upscale_for_msaa) { + /* + //find the closest depth to upscale from, based on neighbours + ivec2 base_coord = ivec2(gl_FragCoord.xy); + float z_dist = gl_FragCoord.z; + ivec2 closest_coord = base_coord; + float closest_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord,0).r-z_dist); + + for(int i=0;i<4;i++) { + const ivec2 neighbours[4]=ivec2[](ivec2(-1,0),ivec2(1,0),ivec2(0,-1),ivec2(0,1)); + ivec2 neighbour_coord = base_coord + neighbours[i]; + float neighbour_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord,0).r-z_dist); + if (neighbour_z_dist < closest_z_dist) { + closest_z_dist = neighbour_z_dist; + closest_coord = neighbour_coord; + } + } + +*/ + ivec2 base_coord = ivec2(gl_FragCoord.xy); + ivec2 closest_coord = base_coord; + float closest_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0).xyz * 2.0 - 1.0); + + for (int i = 0; i < 4; i++) { + const ivec2 neighbours[4] = ivec2[](ivec2(-1, 0), ivec2(1, 0), ivec2(0, -1), ivec2(0, 1)); + ivec2 neighbour_coord = base_coord + neighbours[i]; + float neighbour_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord, 0).xyz * 2.0 - 1.0); + if (neighbour_ang > closest_ang) { + closest_ang = neighbour_ang; + closest_coord = neighbour_coord; + } + } + + coord = closest_coord; + + } else { + coord = ivec2(gl_FragCoord.xy); + } + + vec4 buffer_ambient = texelFetch(sampler2D(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0); + vec4 buffer_reflection = texelFetch(sampler2D(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0); + + ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a); + specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a); + } #endif { // process reflections @@ -2376,6 +2497,97 @@ FRAGMENT_SHADER_CODE #ifdef MODE_RENDER_DEPTH +#ifdef MODE_RENDER_SDF + + { + vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz; + ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size)); + + uint albedo16 = 0x1; //solid flag + albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11; + albedo16 |= clamp(uint(albedo.g * 31.0), 0, 31) << 6; + albedo16 |= clamp(uint(albedo.b * 31.0), 0, 31) << 1; + + imageStore(albedo_volume_grid, grid_pos, uvec4(albedo16)); + + uint facing_bits = 0; + const vec3 aniso_dir[6] = vec3[]( + vec3(1, 0, 0), + vec3(0, 1, 0), + vec3(0, 0, 1), + vec3(-1, 0, 0), + vec3(0, -1, 0), + vec3(0, 0, -1)); + + vec3 cam_normal = mat3(scene_data.camera_matrix) * normalize(normal_interp); + + float closest_dist = -1e20; + + for (uint i = 0; i < 6; i++) { + float d = dot(cam_normal, aniso_dir[i]); + if (d > closest_dist) { + closest_dist = d; + facing_bits = (1 << i); + } + } + + imageAtomicOr(geom_facing_grid, grid_pos, facing_bits); //store facing bits + + if (length(emission) > 0.001) { + float lumas[6]; + vec3 light_total = vec3(0); + + for (int i = 0; i < 6; i++) { + float strength = max(0.0, dot(cam_normal, aniso_dir[i])); + vec3 light = emission * strength; + light_total += light; + lumas[i] = max(light.r, max(light.g, light.b)); + } + + float luma_total = max(light_total.r, max(light_total.g, light_total.b)); + + uint light_aniso = 0; + + for (int i = 0; i < 6; i++) { + light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5); + } + + //compress to RGBE9995 to save space + + const float pow2to9 = 512.0f; + const float B = 15.0f; + const float N = 9.0f; + const float LN2 = 0.6931471805599453094172321215; + + float cRed = clamp(light_total.r, 0.0, 65408.0); + float cGreen = clamp(light_total.g, 0.0, 65408.0); + float cBlue = clamp(light_total.b, 0.0, 65408.0); + + float cMax = max(cRed, max(cGreen, cBlue)); + + float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B; + + float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f); + + float exps = expp + 1.0f; + + if (0.0 <= sMax && sMax < pow2to9) { + exps = expp; + } + + float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f); + float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f); + float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f); + //store as 8985 to have 2 extra neighbour bits + uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25); + + imageStore(emission_grid, grid_pos, uvec4(light_rgbe)); + imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso)); + } + } + +#endif + #ifdef MODE_RENDER_MATERIAL albedo_output_buffer.rgb = albedo; @@ -2398,11 +2610,21 @@ FRAGMENT_SHADER_CODE emission_output_buffer.a = 0.0; #endif -#ifdef MODE_RENDER_NORMAL - normal_output_buffer = vec4(normal * 0.5 + 0.5, 0.0); -#ifdef MODE_RENDER_ROUGHNESS - roughness_output_buffer = roughness; -#endif //MODE_RENDER_ROUGHNESS +#ifdef MODE_RENDER_NORMAL_ROUGHNESS + normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness); + +#ifdef MODE_RENDER_GIPROBE + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes + uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; + uint index2 = instances.data[instance_index].gi_offset >> 16; + giprobe_buffer.x = index1 & 0xFF; + giprobe_buffer.y = index2 & 0xFF; + } else { + giprobe_buffer.x = 0xFF; + giprobe_buffer.y = 0xFF; + } +#endif + #endif //MODE_RENDER_NORMAL //nothing happens, so a tree-ssa optimizer will result in no fragment shader :) @@ -2455,7 +2677,6 @@ FRAGMENT_SHADER_CODE #endif diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength); specular_buffer = vec4(specular_light, metallic); - #endif #else //MODE_MULTIPLE_RENDER_TARGETS diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl index 1cac12406a..1244599097 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl @@ -1,6 +1,8 @@ #define M_PI 3.14159265359 #define ROUGHNESS_MAX_LOD 5 +#define MAX_GI_PROBES 8 + layout(push_constant, binding = 0, std430) uniform DrawCall { uint instance_index; uint pad; //16 bits minimum size @@ -27,6 +29,8 @@ layout(set = 0, binding = 1) uniform sampler material_samplers[12]; layout(set = 0, binding = 2) uniform sampler shadow_sampler; +#define SDFGI_MAX_CASCADES 8 + layout(set = 0, binding = 3, std140) uniform SceneData { mat4 projection_matrix; mat4 inv_projection_matrix; @@ -76,11 +80,19 @@ layout(set = 0, binding = 3, std140) uniform SceneData { float ssao_ao_affect; bool roughness_limiter_enabled; + float roughness_limiter_amount; + float roughness_limiter_limit; + uvec2 roughness_limiter_pad; + vec4 ao_color; + + mat4 sdf_to_bounds; + + ivec3 sdf_offset; bool material_uv2_mode; - uint pad_material0; - uint pad_material1; - uint pad_material2; + + ivec3 sdf_size; + bool gi_upscale_for_msaa; #if 0 vec4 ambient_light_color; @@ -120,6 +132,8 @@ layout(set = 0, binding = 3, std140) uniform SceneData { scene_data; +#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6) +#define INSTANCE_FLAGS_USE_SDFGI (1 << 7) #define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8) #define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9) #define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10) @@ -175,13 +189,18 @@ layout(set = 0, binding = 5, std430) restrict readonly buffer Lights { } lights; +#define REFLECTION_AMBIENT_DISABLED 0 +#define REFLECTION_AMBIENT_ENVIRONMENT 1 +#define REFLECTION_AMBIENT_COLOR 2 + struct ReflectionData { vec3 box_extents; float index; vec3 box_offset; uint mask; vec4 params; // intensity, 0, interior , boxproject - vec4 ambient; // ambient color, energy + vec3 ambient; // ambient color + uint ambient_mode; mat4 local_matrix; // up to here for spot and omni, rest is for directional // notes: for ambientblend, use distance to edge to blend between already existing global environment }; @@ -229,29 +248,6 @@ layout(set = 0, binding = 7, std140) uniform DirectionalLights { } directional_lights; -struct GIProbeData { - mat4 xform; - vec3 bounds; - float dynamic_range; - - float bias; - float normal_bias; - bool blend_ambient; - uint texture_slot; - - float anisotropy_strength; - float ambient_occlusion; - float ambient_occlusion_size; - uint pad2; -}; - -layout(set = 0, binding = 8, std140) uniform GIProbes { - GIProbeData data[MAX_GI_PROBES]; -} -gi_probes; - -layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES]; - #define LIGHTMAP_FLAG_USE_DIRECTION 1 #define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2 @@ -319,6 +315,41 @@ layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableDat } global_variables; +struct SDFGIProbeCascadeData { + vec3 position; + float to_probe; + ivec3 probe_world_offset; + float to_cell; // 1/bounds * grid_size +}; + +layout(set = 0, binding = 20, std140) uniform SDFGI { + vec3 grid_size; + uint max_cascades; + + bool use_occlusion; + int probe_axis_size; + float probe_to_uvw; + float normal_bias; + + vec3 lightprobe_tex_pixel_size; + float energy; + + vec3 lightprobe_uv_offset; + float y_mult; + + vec3 occlusion_clamp; + uint pad3; + + vec3 occlusion_renormalize; + uint pad4; + + vec3 cascade_probe_size; + uint pad5; + + SDFGIProbeCascadeData cascades[SDFGI_MAX_CASCADES]; +} +sdfgi; + // decal atlas /* Set 1, Radiance */ @@ -339,13 +370,57 @@ layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; layout(set = 2, binding = 1) uniform texture2D shadow_atlas; +layout(set = 2, binding = 2) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; + /* Set 3, Render Buffers */ +#ifdef MODE_RENDER_SDF + +layout(r16ui, set = 3, binding = 0) uniform restrict writeonly uimage3D albedo_volume_grid; +layout(r32ui, set = 3, binding = 1) uniform restrict writeonly uimage3D emission_grid; +layout(r32ui, set = 3, binding = 2) uniform restrict writeonly uimage3D emission_aniso_grid; +layout(r32ui, set = 3, binding = 3) uniform restrict uimage3D geom_facing_grid; + +//still need to be present for shaders that use it, so remap them to something +#define depth_buffer shadow_atlas +#define color_buffer shadow_atlas +#define normal_roughness_buffer shadow_atlas + +#else + layout(set = 3, binding = 0) uniform texture2D depth_buffer; layout(set = 3, binding = 1) uniform texture2D color_buffer; -layout(set = 3, binding = 2) uniform texture2D normal_buffer; -layout(set = 3, binding = 3) uniform texture2D roughness_buffer; +layout(set = 3, binding = 2) uniform texture2D normal_roughness_buffer; layout(set = 3, binding = 4) uniform texture2D ao_buffer; +layout(set = 3, binding = 5) uniform texture2D ambient_buffer; +layout(set = 3, binding = 6) uniform texture2D reflection_buffer; + +layout(set = 3, binding = 7) uniform texture2DArray sdfgi_lightprobe_texture; + +layout(set = 3, binding = 8) uniform texture3D sdfgi_occlusion_cascades; + +struct GIProbeData { + mat4 xform; + vec3 bounds; + float dynamic_range; + + float bias; + float normal_bias; + bool blend_ambient; + uint texture_slot; + + float anisotropy_strength; + float ambient_occlusion; + float ambient_occlusion_size; + uint pad2; +}; + +layout(set = 3, binding = 9, std140) uniform GIProbes { + GIProbeData data[MAX_GI_PROBES]; +} +gi_probes; + +#endif /* Set 4 Skeleton & Instancing (Multimesh) */ diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl index 084f28d932..a8ee33a664 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl @@ -12,11 +12,8 @@ layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2D ssr_ima #ifdef MODE_ROUGH layout(r8, set = 1, binding = 1) uniform restrict writeonly image2D blur_radius_image; #endif -layout(rgba8, set = 2, binding = 0) uniform restrict readonly image2D source_normal; +layout(rgba8, set = 2, binding = 0) uniform restrict readonly image2D source_normal_roughness; layout(set = 3, binding = 0) uniform sampler2D source_metallic; -#ifdef MODE_ROUGH -layout(set = 3, binding = 1) uniform sampler2D source_roughness; -#endif layout(push_constant, binding = 2, std430) uniform Params { vec4 proj_info; @@ -75,7 +72,8 @@ void main() { // World space point being shaded vec3 vertex = reconstructCSPosition(uv * vec2(params.screen_size), base_depth); - vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0; + vec4 normal_roughness = imageLoad(source_normal_roughness, ssC); + vec3 normal = normal_roughness.xyz * 2.0 - 1.0; normal = normalize(normal); normal.y = -normal.y; //because this code reads flipped @@ -208,7 +206,7 @@ void main() { // if roughness is enabled, do screen space cone tracing float blur_radius = 0.0; - float roughness = texelFetch(source_roughness, ssC << 1, 0).r; + float roughness = normal_roughness.w; if (roughness > 0.001) { float cone_angle = min(roughness, 0.999) * M_PI * 0.5; diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl new file mode 100644 index 0000000000..813ea29fa1 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_debug.glsl @@ -0,0 +1,275 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#define MAX_CASCADES 8 + +layout(set = 0, binding = 1) uniform texture3D sdf_cascades[MAX_CASCADES]; +layout(set = 0, binding = 2) uniform texture3D light_cascades[MAX_CASCADES]; +layout(set = 0, binding = 3) uniform texture3D aniso0_cascades[MAX_CASCADES]; +layout(set = 0, binding = 4) uniform texture3D aniso1_cascades[MAX_CASCADES]; +layout(set = 0, binding = 5) uniform texture3D occlusion_texture; + +layout(set = 0, binding = 8) uniform sampler linear_sampler; + +struct CascadeData { + vec3 offset; //offset of (0,0,0) in world coordinates + float to_cell; // 1/bounds * grid_size + ivec3 probe_world_offset; + uint pad; +}; + +layout(set = 0, binding = 9, std140) uniform Cascades { + CascadeData data[MAX_CASCADES]; +} +cascades; + +layout(rgba16f, set = 0, binding = 10) uniform restrict writeonly image2D screen_buffer; + +layout(set = 0, binding = 11) uniform texture2DArray lightprobe_texture; + +layout(push_constant, binding = 0, std430) uniform Params { + vec3 grid_size; + uint max_cascades; + + ivec2 screen_size; + bool use_occlusion; + float y_mult; + + vec3 cam_extent; + int probe_axis_size; + + mat4 cam_transform; +} +params; + +vec3 linear_to_srgb(vec3 color) { + //if going to srgb, clamp from 0 to 1. + color = clamp(color, vec3(0.0), vec3(1.0)); + const vec3 a = vec3(0.055f); + return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); +} + +vec2 octahedron_wrap(vec2 v) { + vec2 signVal; + signVal.x = v.x >= 0.0 ? 1.0 : -1.0; + signVal.y = v.y >= 0.0 ? 1.0 : -1.0; + return (1.0 - abs(v.yx)) * signVal; +} + +vec2 octahedron_encode(vec3 n) { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; +} + +void main() { + // Pixel being shaded + ivec2 screen_pos = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(screen_pos, params.screen_size))) { //too large, do nothing + return; + } + + vec3 ray_pos; + vec3 ray_dir; + { + ray_pos = params.cam_transform[3].xyz; + + ray_dir.xy = params.cam_extent.xy * ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0); + ray_dir.z = params.cam_extent.z; + + ray_dir = normalize(mat3(params.cam_transform) * ray_dir); + } + + ray_pos.y *= params.y_mult; + ray_dir.y *= params.y_mult; + ray_dir = normalize(ray_dir); + + vec3 pos_to_uvw = 1.0 / params.grid_size; + + vec3 light = vec3(0.0); + float blend = 0.0; + +#if 1 + vec3 inv_dir = 1.0 / ray_dir; + + float rough = 0.5; + bool hit = false; + + for (uint i = 0; i < params.max_cascades; i++) { + //convert to local bounds + vec3 pos = ray_pos - cascades.data[i].offset; + pos *= cascades.data[i].to_cell; + + // Should never happen for debug, since we start mostly at the bounds center, + // but add anyway. + //if (any(lessThan(pos,vec3(0.0))) || any(greaterThanEqual(pos,params.grid_size))) { + // continue; //already past bounds for this cascade, goto next + //} + + //find maximum advance distance (until reaching bounds) + vec3 t0 = -pos * inv_dir; + vec3 t1 = (params.grid_size - pos) * inv_dir; + vec3 tmax = max(t0, t1); + float max_advance = min(tmax.x, min(tmax.y, tmax.z)); + + float advance = 0.0; + vec3 uvw; + hit = false; + + while (advance < max_advance) { + //read how much to advance from SDF + uvw = (pos + ray_dir * advance) * pos_to_uvw; + + float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), uvw).r * 255.0 - 1.7; + + if (distance < 0.001) { + //consider hit + hit = true; + break; + } + + advance += distance; + } + + if (!hit) { + pos += ray_dir * min(advance, max_advance); + pos /= cascades.data[i].to_cell; + pos += cascades.data[i].offset; + ray_pos = pos; + continue; + } + + //compute albedo, emission and normal at hit point + + const float EPSILON = 0.001; + vec3 hit_normal = normalize(vec3( + texture(sampler3D(sdf_cascades[i], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[i], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r, + texture(sampler3D(sdf_cascades[i], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[i], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r, + texture(sampler3D(sdf_cascades[i], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[i], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r)); + + vec3 hit_light = texture(sampler3D(light_cascades[i], linear_sampler), uvw).rgb; + vec4 aniso0 = texture(sampler3D(aniso0_cascades[i], linear_sampler), uvw); + vec3 hit_aniso0 = aniso0.rgb; + vec3 hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[i], linear_sampler), uvw).rg); + + hit_light *= (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0))); + + if (blend > 0.0) { + light = mix(light, hit_light, blend); + blend = 0.0; + } else { + light = hit_light; + + //process blend + float blend_from = (float(params.probe_axis_size - 1) / 2.0) - 2.5; + float blend_to = blend_from + 2.0; + + vec3 cam_pos = params.cam_transform[3].xyz - cascades.data[i].offset; + cam_pos *= cascades.data[i].to_cell; + + pos += ray_dir * min(advance, max_advance); + vec3 inner_pos = pos - cam_pos; + + inner_pos = inner_pos * float(params.probe_axis_size - 1) / params.grid_size.x; + + float len = length(inner_pos); + + inner_pos = abs(normalize(inner_pos)); + len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z)); + + if (len >= blend_from) { + blend = smoothstep(blend_from, blend_to, len); + + pos /= cascades.data[i].to_cell; + pos += cascades.data[i].offset; + ray_pos = pos; + hit = false; //continue trace for blend + + continue; + } + } + + break; + } + + light = mix(light, vec3(0.0), blend); + +#else + + vec3 inv_dir = 1.0 / ray_dir; + + bool hit = false; + vec4 light_accum = vec4(0.0); + + float blend_size = (params.grid_size.x / float(params.probe_axis_size - 1)) * 0.5; + + float radius_sizes[MAX_CASCADES]; + for (uint i = 0; i < params.max_cascades; i++) { + radius_sizes[i] = (1.0 / cascades.data[i].to_cell) * (params.grid_size.x * 0.5 - blend_size); + } + + float max_distance = radius_sizes[params.max_cascades - 1]; + float advance = 0; + while (advance < max_distance) { + for (uint i = 0; i < params.max_cascades; i++) { + if (advance < radius_sizes[i]) { + vec3 pos = (ray_pos + ray_dir * advance) - cascades.data[i].offset; + pos *= cascades.data[i].to_cell * pos_to_uvw; + + float distance = texture(sampler3D(sdf_cascades[i], linear_sampler), pos).r * 255.0 - 1.0; + + vec4 hit_light = vec4(0.0); + if (distance < 1.0) { + hit_light.a = max(0.0, 1.0 - distance); + hit_light.rgb = texture(sampler3D(light_cascades[i], linear_sampler), pos).rgb; + hit_light.rgb *= hit_light.a; + } + + distance /= cascades.data[i].to_cell; + + if (i < (params.max_cascades - 1)) { + pos = (ray_pos + ray_dir * advance) - cascades.data[i + 1].offset; + pos *= cascades.data[i + 1].to_cell * pos_to_uvw; + + float distance2 = texture(sampler3D(sdf_cascades[i + 1], linear_sampler), pos).r * 255.0 - 1.0; + + vec4 hit_light2 = vec4(0.0); + if (distance2 < 1.0) { + hit_light2.a = max(0.0, 1.0 - distance2); + hit_light2.rgb = texture(sampler3D(light_cascades[i + 1], linear_sampler), pos).rgb; + hit_light2.rgb *= hit_light2.a; + } + + float prev_radius = i == 0 ? 0.0 : radius_sizes[i - 1]; + float blend = (advance - prev_radius) / (radius_sizes[i] - prev_radius); + + distance2 /= cascades.data[i + 1].to_cell; + + hit_light = mix(hit_light, hit_light2, blend); + distance = mix(distance, distance2, blend); + } + + light_accum += hit_light; + advance += distance; + break; + } + } + + if (light_accum.a > 0.98) { + break; + } + } + + light = light_accum.rgb / light_accum.a; + +#endif + + imageStore(screen_buffer, screen_pos, vec4(linear_to_srgb(light), 1.0)); +} diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl new file mode 100644 index 0000000000..08da283dad --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_debug_probes.glsl @@ -0,0 +1,231 @@ +#[vertex] + +#version 450 + +VERSION_DEFINES + +#define MAX_CASCADES 8 + +layout(push_constant, binding = 0, std430) uniform Params { + mat4 projection; + + uint band_power; + uint sections_in_band; + uint band_mask; + float section_arc; + + vec3 grid_size; + uint cascade; + + uint pad; + float y_mult; + uint probe_debug_index; + int probe_axis_size; +} +params; + +// http://in4k.untergrund.net/html_articles/hugi_27_-_coding_corner_polaris_sphere_tessellation_101.htm + +vec3 get_sphere_vertex(uint p_vertex_id) { + float x_angle = float(p_vertex_id & 1u) + (p_vertex_id >> params.band_power); + + float y_angle = + float((p_vertex_id & params.band_mask) >> 1) + ((p_vertex_id >> params.band_power) * params.sections_in_band); + + x_angle *= params.section_arc * 0.5f; // remember - 180AA x rot not 360 + y_angle *= -params.section_arc; + + vec3 point = vec3(sin(x_angle) * sin(y_angle), cos(x_angle), sin(x_angle) * cos(y_angle)); + + return point; +} + +#ifdef MODE_PROBES + +layout(location = 0) out vec3 normal_interp; +layout(location = 1) out flat uint probe_index; + +#endif + +#ifdef MODE_VISIBILITY + +layout(location = 0) out float visibility; + +#endif + +struct CascadeData { + vec3 offset; //offset of (0,0,0) in world coordinates + float to_cell; // 1/bounds * grid_size + ivec3 probe_world_offset; + uint pad; +}; + +layout(set = 0, binding = 1, std140) uniform Cascades { + CascadeData data[MAX_CASCADES]; +} +cascades; + +layout(set = 0, binding = 4) uniform texture3D occlusion_texture; +layout(set = 0, binding = 3) uniform sampler linear_sampler; + +void main() { +#ifdef MODE_PROBES + probe_index = gl_InstanceIndex; + + normal_interp = get_sphere_vertex(gl_VertexIndex); + + vec3 vertex = normal_interp * 0.2; + + float probe_cell_size = float(params.grid_size / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell; + + ivec3 probe_cell; + probe_cell.x = int(probe_index % params.probe_axis_size); + probe_cell.y = int(probe_index / (params.probe_axis_size * params.probe_axis_size)); + probe_cell.z = int((probe_index / params.probe_axis_size) % params.probe_axis_size); + + vertex += (cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size) / vec3(1.0, params.y_mult, 1.0); + + gl_Position = params.projection * vec4(vertex, 1.0); +#endif + +#ifdef MODE_VISIBILITY + + int probe_index = int(params.probe_debug_index); + + vec3 vertex = get_sphere_vertex(gl_VertexIndex) * 0.01; + + float probe_cell_size = float(params.grid_size / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell; + + ivec3 probe_cell; + probe_cell.x = int(probe_index % params.probe_axis_size); + probe_cell.y = int((probe_index % (params.probe_axis_size * params.probe_axis_size)) / params.probe_axis_size); + probe_cell.z = int(probe_index / (params.probe_axis_size * params.probe_axis_size)); + + vertex += (cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size) / vec3(1.0, params.y_mult, 1.0); + + int probe_voxels = int(params.grid_size.x) / int(params.probe_axis_size - 1); + int occluder_index = int(gl_InstanceIndex); + + int diameter = probe_voxels * 2; + ivec3 occluder_pos; + occluder_pos.x = int(occluder_index % diameter); + occluder_pos.y = int(occluder_index / (diameter * diameter)); + occluder_pos.z = int((occluder_index / diameter) % diameter); + + float cell_size = 1.0 / cascades.data[params.cascade].to_cell; + + ivec3 occluder_offset = occluder_pos - ivec3(diameter / 2); + vertex += ((vec3(occluder_offset) + vec3(0.5)) * cell_size) / vec3(1.0, params.y_mult, 1.0); + + ivec3 global_cell = probe_cell + cascades.data[params.cascade].probe_world_offset; + uint occlusion_layer = 0; + if ((global_cell.x & 1) != 0) { + occlusion_layer |= 1; + } + if ((global_cell.y & 1) != 0) { + occlusion_layer |= 2; + } + if ((global_cell.z & 1) != 0) { + occlusion_layer |= 4; + } + ivec3 tex_pos = probe_cell * probe_voxels + occluder_offset; + + const vec4 layer_axis[4] = vec4[]( + vec4(1, 0, 0, 0), + vec4(0, 1, 0, 0), + vec4(0, 0, 1, 0), + vec4(0, 0, 0, 1)); + + tex_pos.z += int(params.cascade) * int(params.grid_size); + if (occlusion_layer >= 4) { + tex_pos.x += int(params.grid_size.x); + occlusion_layer &= 3; + } + + visibility = dot(texelFetch(sampler3D(occlusion_texture, linear_sampler), tex_pos, 0), layer_axis[occlusion_layer]); + + gl_Position = params.projection * vec4(vertex, 1.0); + +#endif +} + +#[fragment] + +#version 450 + +VERSION_DEFINES + +layout(location = 0) out vec4 frag_color; + +layout(set = 0, binding = 2) uniform texture2DArray lightprobe_texture; +layout(set = 0, binding = 3) uniform sampler linear_sampler; + +layout(push_constant, binding = 0, std430) uniform Params { + mat4 projection; + + uint band_power; + uint sections_in_band; + uint band_mask; + float section_arc; + + vec3 grid_size; + uint cascade; + + uint pad; + float y_mult; + uint probe_debug_index; + int probe_axis_size; +} +params; + +#ifdef MODE_PROBES + +layout(location = 0) in vec3 normal_interp; +layout(location = 1) in flat uint probe_index; + +#endif + +#ifdef MODE_VISIBILITY +layout(location = 0) in float visibility; +#endif + +vec2 octahedron_wrap(vec2 v) { + vec2 signVal; + signVal.x = v.x >= 0.0 ? 1.0 : -1.0; + signVal.y = v.y >= 0.0 ? 1.0 : -1.0; + return (1.0 - abs(v.yx)) * signVal; +} + +vec2 octahedron_encode(vec3 n) { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; +} + +void main() { +#ifdef MODE_PROBES + + ivec3 tex_pos; + tex_pos.x = int(probe_index) % params.probe_axis_size; //x + tex_pos.y = int(probe_index) / (params.probe_axis_size * params.probe_axis_size); + tex_pos.x += params.probe_axis_size * ((int(probe_index) / params.probe_axis_size) % params.probe_axis_size); //z + tex_pos.z = int(params.cascade); + + vec3 tex_pos_ofs = vec3(octahedron_encode(normal_interp) * float(OCT_SIZE), 0.0); + vec3 tex_posf = vec3(vec2(tex_pos.xy * (OCT_SIZE + 2) + ivec2(1)), float(tex_pos.z)) + tex_pos_ofs; + + tex_posf.xy /= vec2(ivec2(params.probe_axis_size * params.probe_axis_size * (OCT_SIZE + 2), params.probe_axis_size * (OCT_SIZE + 2))); + + vec4 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), tex_posf, 0.0); + + frag_color = indirect_light; + +#endif + +#ifdef MODE_VISIBILITY + + frag_color = vec4(vec3(1, visibility, visibility), 1.0); +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl new file mode 100644 index 0000000000..c4b29216d5 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_direct_light.glsl @@ -0,0 +1,472 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +#define MAX_CASCADES 8 + +layout(set = 0, binding = 1) uniform texture3D sdf_cascades[MAX_CASCADES]; +layout(set = 0, binding = 2) uniform sampler linear_sampler; + +layout(set = 0, binding = 3, std430) restrict readonly buffer DispatchData { + uint x; + uint y; + uint z; + uint total_count; +} +dispatch_data; + +struct ProcessVoxel { + uint position; //xyz 7 bit packed, extra 11 bits for neigbours + uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbous + uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours + //total neighbours: 26 +}; + +#ifdef MODE_PROCESS_STATIC +layout(set = 0, binding = 4, std430) restrict buffer ProcessVoxels { +#else +layout(set = 0, binding = 4, std430) restrict buffer readonly ProcessVoxels { +#endif + ProcessVoxel data[]; +} +process_voxels; + +layout(r32ui, set = 0, binding = 5) uniform restrict uimage3D dst_light; +layout(rgba8, set = 0, binding = 6) uniform restrict image3D dst_aniso0; +layout(rg8, set = 0, binding = 7) uniform restrict image3D dst_aniso1; + +struct CascadeData { + vec3 offset; //offset of (0,0,0) in world coordinates + float to_cell; // 1/bounds * grid_size + ivec3 probe_world_offset; + uint pad; +}; + +layout(set = 0, binding = 8, std140) uniform Cascades { + CascadeData data[MAX_CASCADES]; +} +cascades; + +#define LIGHT_TYPE_DIRECTIONAL 0 +#define LIGHT_TYPE_OMNI 1 +#define LIGHT_TYPE_SPOT 2 + +struct Light { + vec3 color; + float energy; + + vec3 direction; + bool has_shadow; + + vec3 position; + float attenuation; + + uint type; + float spot_angle; + float spot_attenuation; + float radius; + + vec4 shadow_color; +}; + +layout(set = 0, binding = 9, std140) buffer restrict readonly Lights { + Light data[]; +} +lights; + +layout(set = 0, binding = 10) uniform texture2DArray lightprobe_texture; + +layout(push_constant, binding = 0, std430) uniform Params { + vec3 grid_size; + uint max_cascades; + + uint cascade; + uint light_count; + uint process_offset; + uint process_increment; + + int probe_axis_size; + bool multibounce; + float y_mult; + uint pad; +} +params; + +vec2 octahedron_wrap(vec2 v) { + vec2 signVal; + signVal.x = v.x >= 0.0 ? 1.0 : -1.0; + signVal.y = v.y >= 0.0 ? 1.0 : -1.0; + return (1.0 - abs(v.yx)) * signVal; +} + +vec2 octahedron_encode(vec3 n) { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + n /= (abs(n.x) + abs(n.y) + abs(n.z)); + n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy); + n.xy = n.xy * 0.5 + 0.5; + return n.xy; +} + +void main() { + uint voxel_index = uint(gl_GlobalInvocationID.x); + + //used for skipping voxels every N frames + voxel_index = params.process_offset + voxel_index * params.process_increment; + + if (voxel_index >= dispatch_data.total_count) { + return; + } + + uint voxel_position = process_voxels.data[voxel_index].position; + + //keep for storing to texture + ivec3 positioni = ivec3((uvec3(voxel_position, voxel_position, voxel_position) >> uvec3(0, 7, 14)) & uvec3(0x7F)); + + vec3 position = vec3(positioni) + vec3(0.5); + position /= cascades.data[params.cascade].to_cell; + position += cascades.data[params.cascade].offset; + + uint voxel_albedo = process_voxels.data[voxel_index].albedo; + + vec3 albedo = vec3(uvec3(voxel_albedo >> 10, voxel_albedo >> 5, voxel_albedo) & uvec3(0x1F)) / float(0x1F); + vec3 light_accum[6]; + + uint valid_aniso = (voxel_albedo >> 15) & 0x3F; + + { + uint rgbe = process_voxels.data[voxel_index].light; + + //read rgbe8985 + float r = float((rgbe & 0xff) << 1); + float g = float((rgbe >> 8) & 0x1ff); + float b = float(((rgbe >> 17) & 0xff) << 1); + float e = float((rgbe >> 25) & 0x1F); + float m = pow(2.0, e - 15.0 - 9.0); + + vec3 l = vec3(r, g, b) * m; + + uint aniso = process_voxels.data[voxel_index].light_aniso; + for (uint i = 0; i < 6; i++) { + float strength = ((aniso >> (i * 5)) & 0x1F) / float(0x1F); + light_accum[i] = l * strength; + } + } + + const vec3 aniso_dir[6] = vec3[]( + vec3(1, 0, 0), + vec3(0, 1, 0), + vec3(0, 0, 1), + vec3(-1, 0, 0), + vec3(0, -1, 0), + vec3(0, 0, -1)); + + // Raytrace light + + vec3 pos_to_uvw = 1.0 / params.grid_size; + vec3 uvw_ofs = pos_to_uvw * 0.5; + + for (uint i = 0; i < params.light_count; i++) { + float attenuation = 1.0; + vec3 direction; + float light_distance = 1e20; + + switch (lights.data[i].type) { + case LIGHT_TYPE_DIRECTIONAL: { + direction = -lights.data[i].direction; + } break; + case LIGHT_TYPE_OMNI: { + vec3 rel_vec = lights.data[i].position - position; + direction = normalize(rel_vec); + light_distance = length(rel_vec); + rel_vec.y /= params.y_mult; + attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation); + } break; + case LIGHT_TYPE_SPOT: { + vec3 rel_vec = lights.data[i].position - position; + direction = normalize(rel_vec); + light_distance = length(rel_vec); + rel_vec.y /= params.y_mult; + attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation); + + float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction)); + if (angle > lights.data[i].spot_angle) { + attenuation = 0.0; + } else { + float d = clamp(angle / lights.data[i].spot_angle, 0, 1); + attenuation *= pow(1.0 - d, lights.data[i].spot_attenuation); + } + } break; + } + + if (attenuation < 0.001) { + continue; + } + + bool hit = false; + + vec3 ray_pos = position; + vec3 ray_dir = direction; + vec3 inv_dir = 1.0 / ray_dir; + + //this is how to properly bias outgoing rays + float cell_size = 1.0 / cascades.data[params.cascade].to_cell; + ray_pos += sign(direction) * cell_size * 0.48; // go almost to the box edge but remain inside + ray_pos += ray_dir * 0.4 * cell_size; //apply a small bias from there + + for (uint j = params.cascade; j < params.max_cascades; j++) { + //convert to local bounds + vec3 pos = ray_pos - cascades.data[j].offset; + pos *= cascades.data[j].to_cell; + float local_distance = light_distance * cascades.data[j].to_cell; + + if (any(lessThan(pos, vec3(0.0))) || any(greaterThanEqual(pos, params.grid_size))) { + continue; //already past bounds for this cascade, goto next + } + + //find maximum advance distance (until reaching bounds) + vec3 t0 = -pos * inv_dir; + vec3 t1 = (params.grid_size - pos) * inv_dir; + vec3 tmax = max(t0, t1); + float max_advance = min(tmax.x, min(tmax.y, tmax.z)); + + max_advance = min(local_distance, max_advance); + + float advance = 0.0; + float occlusion = 1.0; + + while (advance < max_advance) { + //read how much to advance from SDF + vec3 uvw = (pos + ray_dir * advance) * pos_to_uvw; + + float distance = texture(sampler3D(sdf_cascades[j], linear_sampler), uvw).r * 255.0 - 1.0; + if (distance < 0.001) { + //consider hit + hit = true; + break; + } + + occlusion = min(occlusion, distance); + + advance += distance; + } + + if (hit) { + attenuation *= occlusion; + break; + } + + if (advance >= local_distance) { + break; //past light distance, abandon search + } + //change ray origin to collision with bounds + pos += ray_dir * max_advance; + pos /= cascades.data[j].to_cell; + pos += cascades.data[j].offset; + light_distance -= max_advance / cascades.data[j].to_cell; + ray_pos = pos; + } + + if (!hit) { + vec3 light = albedo * lights.data[i].color.rgb * lights.data[i].energy * attenuation; + + for (int j = 0; j < 6; j++) { + if (bool(valid_aniso & (1 << j))) { + light_accum[j] += max(0.0, dot(aniso_dir[j], direction)) * light; + } + } + } + } + + // Add indirect light + + if (params.multibounce) { + vec3 pos = (vec3(positioni) + vec3(0.5)) * float(params.probe_axis_size - 1) / params.grid_size; + ivec3 probe_base_pos = ivec3(pos); + + vec4 probe_accum[6] = vec4[](vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0), vec4(0.0)); + float weight_accum[6] = float[](0, 0, 0, 0, 0, 0); + + ivec3 tex_pos = ivec3(probe_base_pos.xy, int(params.cascade)); + tex_pos.x += probe_base_pos.z * int(params.probe_axis_size); + + tex_pos.xy = tex_pos.xy * (OCT_SIZE + 2) + ivec2(1); + + vec3 base_tex_posf = vec3(tex_pos); + 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; + + for (uint j = 0; j < 8; j++) { + ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1); + ivec3 probe_posi = probe_base_pos; + probe_posi += offset; + + // Compute weight + + vec3 probe_pos = vec3(probe_posi); + vec3 probe_to_pos = pos - probe_pos; + vec3 probe_dir = normalize(-probe_to_pos); + + // Compute lightprobe texture position + + vec3 trilinear = vec3(1.0) - abs(probe_to_pos); + + for (uint k = 0; k < 6; k++) { + if (bool(valid_aniso & (1 << k))) { + vec3 n = aniso_dir[k]; + float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(n, probe_dir)); + + vec3 tex_posf = base_tex_posf + vec3(octahedron_encode(n) * float(OCT_SIZE), 0.0); + tex_posf.xy *= tex_pixel_size; + + vec3 pos_uvw = tex_posf; + pos_uvw.xy += vec2(offset.xy) * probe_uv_offset.xy; + pos_uvw.x += float(offset.z) * probe_uv_offset.z; + vec4 indirect_light = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0); + + probe_accum[k] += indirect_light * weight; + weight_accum[k] += weight; + } + } + } + + for (uint k = 0; k < 6; k++) { + if (weight_accum[k] > 0.0) { + light_accum[k] += probe_accum[k].rgb * albedo / weight_accum[k]; + } + } + } + + // Store the light in the light texture + + float lumas[6]; + vec3 light_total = vec3(0); + + for (int i = 0; i < 6; i++) { + light_total += light_accum[i]; + lumas[i] = max(light_accum[i].r, max(light_accum[i].g, light_accum[i].b)); + } + + float luma_total = max(light_total.r, max(light_total.g, light_total.b)); + + uint light_total_rgbe; + + { + //compress to RGBE9995 to save space + + const float pow2to9 = 512.0f; + const float B = 15.0f; + const float N = 9.0f; + const float LN2 = 0.6931471805599453094172321215; + + float cRed = clamp(light_total.r, 0.0, 65408.0); + float cGreen = clamp(light_total.g, 0.0, 65408.0); + float cBlue = clamp(light_total.b, 0.0, 65408.0); + + float cMax = max(cRed, max(cGreen, cBlue)); + + float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B; + + float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f); + + float exps = expp + 1.0f; + + if (0.0 <= sMax && sMax < pow2to9) { + exps = expp; + } + + float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f); + float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f); + float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f); +#ifdef MODE_PROCESS_STATIC + //since its self-save, use RGBE8985 + light_total_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25); + +#else + light_total_rgbe = (uint(sRed) & 0x1FF) | ((uint(sGreen) & 0x1FF) << 9) | ((uint(sBlue) & 0x1FF) << 18) | ((uint(exps) & 0x1F) << 27); +#endif + } + +#ifdef MODE_PROCESS_DYNAMIC + + vec4 aniso0; + aniso0.r = lumas[0] / luma_total; + aniso0.g = lumas[1] / luma_total; + aniso0.b = lumas[2] / luma_total; + aniso0.a = lumas[3] / luma_total; + + vec2 aniso1; + aniso1.r = lumas[4] / luma_total; + aniso1.g = lumas[5] / luma_total; + + //save to 3D textures + imageStore(dst_aniso0, positioni, aniso0); + imageStore(dst_aniso1, positioni, vec4(aniso1, 0.0, 0.0)); + imageStore(dst_light, positioni, uvec4(light_total_rgbe)); + + //also fill neighbours, so light interpolation during the indirect pass works + + //recover the neighbour list from the leftover bits + uint neighbours = (voxel_albedo >> 21) | ((voxel_position >> 21) << 11) | ((process_voxels.data[voxel_index].light >> 30) << 22) | ((process_voxels.data[voxel_index].light_aniso >> 30) << 24); + + const uint max_neighbours = 26; + const ivec3 neighbour_positions[max_neighbours] = ivec3[]( + ivec3(-1, -1, -1), + ivec3(-1, -1, 0), + ivec3(-1, -1, 1), + ivec3(-1, 0, -1), + ivec3(-1, 0, 0), + ivec3(-1, 0, 1), + ivec3(-1, 1, -1), + ivec3(-1, 1, 0), + ivec3(-1, 1, 1), + ivec3(0, -1, -1), + ivec3(0, -1, 0), + ivec3(0, -1, 1), + ivec3(0, 0, -1), + ivec3(0, 0, 1), + ivec3(0, 1, -1), + ivec3(0, 1, 0), + ivec3(0, 1, 1), + ivec3(1, -1, -1), + ivec3(1, -1, 0), + ivec3(1, -1, 1), + ivec3(1, 0, -1), + ivec3(1, 0, 0), + ivec3(1, 0, 1), + ivec3(1, 1, -1), + ivec3(1, 1, 0), + ivec3(1, 1, 1)); + + for (uint i = 0; i < max_neighbours; i++) { + if (bool(neighbours & (1 << i))) { + ivec3 neighbour_pos = positioni + neighbour_positions[i]; + imageStore(dst_light, neighbour_pos, uvec4(light_total_rgbe)); + imageStore(dst_aniso0, neighbour_pos, aniso0); + imageStore(dst_aniso1, neighbour_pos, vec4(aniso1, 0.0, 0.0)); + } + } + +#endif + +#ifdef MODE_PROCESS_STATIC + + //save back the anisotropic + + uint light = process_voxels.data[voxel_index].light & (3 << 30); + light |= light_total_rgbe; + process_voxels.data[voxel_index].light = light; //replace + + uint light_aniso = process_voxels.data[voxel_index].light_aniso & (3 << 30); + for (int i = 0; i < 6; i++) { + light_aniso |= min(31, uint((lumas[i] / luma_total) * 31.0)) << (i * 5); + } + + process_voxels.data[voxel_index].light_aniso = light_aniso; + +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_fields.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_fields.glsl new file mode 100644 index 0000000000..eec0a90c0d --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_fields.glsl @@ -0,0 +1,182 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = OCT_RES, local_size_y = OCT_RES, local_size_z = 1) in; + +/* clang-format on */ + +#define MAX_CASCADES 8 + +layout(rgba16f, set = 0, binding = 1) uniform restrict image2DArray irradiance_texture; +layout(rg16f, set = 0, binding = 2) uniform restrict image2DArray depth_texture; + +ayout(rgba32ui, set = 0, binding = 3) uniform restrict uimage2DArray irradiance_history_texture; +layout(rg32ui, set = 0, binding = 4) uniform restrict uimage2DArray depth_history_texture; + +struct CascadeData { + vec3 offset; //offset of (0,0,0) in world coordinates + float to_cell; // 1/bounds * grid_size +}; + +layout(set = 0, binding = 5, std140) uniform Cascades { + CascadeData data[MAX_CASCADES]; +} +cascades; + +#define DEPTH_HISTORY_BITS 24 +#define IRRADIANCE_HISTORY_BITS 16 + +layout(push_constant, binding = 0, std430) uniform Params { + vec3 grid_size; + uint max_cascades; + + uint probe_axis_size; + uint cascade; + uint history_size; + uint pad0; + + ivec3 scroll; //scroll in probes + uint pad1; +} +params; + +void main() { + ivec2 local = ivec2(gl_LocalInvocationID.xy); + ivec2 probe = ivec2(gl_WorkGroupID.xy); + + ivec3 probe_cell; + probe_cell.x = probe.x % int(params.probe_axis_size); + probe_cell.y = probe.y; + probe_cell.z = probe.x / int(params.probe_axis_size); + +#ifdef MODE_SCROLL_BEGIN + + ivec3 read_cell = probe_cell - params.scroll; + + uint src_layer = (params.history_size + 1) * params.cascade; + uint dst_layer = (params.history_size + 1) * params.max_cascades; + + for (uint i = 0; i <= params.history_size; i++) { + ivec3 write_pos = ivec3(probe * OCT_RES + local, int(i)); + + if (any(lessThan(read_pos, ivec3(0))) || any(greaterThanEqual(read_pos, ivec3(params.probe_axis_size)))) { + // nowhere to read from for scrolling, try finding the value from upper probes + +#ifdef MODE_IRRADIANCE + imageStore(irradiance_history_texture, write_pos, uvec4(0)); +#endif +#ifdef MODE_DEPTH + imageStore(depth_history_texture, write_pos, uvec4(0)); +#endif + } else { + ivec3 read_pos; + read_pos.xy = read_cell.xy; + read_pos.x += read_cell.z * params.probe_axis_size; + read_pos.xy = read_pos.xy * OCT_RES + local; + read_pos.z = int(i); + +#ifdef MODE_IRRADIANCE + uvec4 value = imageLoad(irradiance_history_texture, read_pos); + imageStore(irradiance_history_texture, write_pos, value); +#endif +#ifdef MODE_DEPTH + uvec2 value = imageLoad(depth_history_texture, read_pos); + imageStore(depth_history_texture, write_pos, value); +#endif + } + } + +#endif // MODE_SCROLL_BEGIN + +#ifdef MODE_SCROLL_END + + uint src_layer = (params.history_size + 1) * params.max_cascades; + uint dst_layer = (params.history_size + 1) * params.cascade; + + for (uint i = 0; i <= params.history_size; i++) { + ivec3 pos = ivec3(probe * OCT_RES + local, int(i)); + +#ifdef MODE_IRRADIANCE + uvec4 value = imageLoad(irradiance_history_texture, read_pos); + imageStore(irradiance_history_texture, write_pos, value); +#endif +#ifdef MODE_DEPTH + uvec2 value = imageLoad(depth_history_texture, read_pos); + imageStore(depth_history_texture, write_pos, value); +#endif + } + +#endif //MODE_SCROLL_END + +#ifdef MODE_STORE + + uint src_layer = (params.history_size + 1) * params.cascade + params.history_size; + ivec3 read_pos = ivec3(probe * OCT_RES + local, int(src_layer)); + + ivec3 write_pos = ivec3(probe * (OCT_RES + 2) + ivec2(1), int(params.cascade)); + + ivec3 copy_to[4] = ivec3[](write_pos, ivec3(-2, -2, -2), ivec3(-2, -2, -2), ivec3(-2, -2, -2)); + +#ifdef MODE_IRRADIANCE + uvec4 average = imageLoad(irradiance_history_texture, read_pos); + vec4 light_accum = vec4(average / params.history_size) / float(1 << IRRADIANCE_HISTORY_BITS); + +#endif +#ifdef MODE_DEPTH + uvec2 value = imageLoad(depth_history_texture, read_pos); + vec2 depth_accum = vec4(average / params.history_size) / float(1 << IRRADIANCE_HISTORY_BITS); + + float probe_cell_size = float(params.grid_size / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell; + float max_depth = length(params.grid_size / cascades.data[params.max_cascades - 1].to_cell); + max_depth /= probe_cell_size; + + depth_value = (vec2(average / params.history_size) / float(1 << DEPTH_HISTORY_BITS)) * vec2(max_depth, max_depth * max_depth); + +#endif + + /* Fill the border if required */ + + if (local == ivec2(0, 0)) { + copy_to[1] = texture_pos + ivec3(OCT_RES - 1, -1, 0); + copy_to[2] = texture_pos + ivec3(-1, OCT_RES - 1, 0); + copy_to[3] = texture_pos + ivec3(OCT_RES, OCT_RES, 0); + } else if (local == ivec2(OCT_RES - 1, 0)) { + copy_to[1] = texture_pos + ivec3(0, -1, 0); + copy_to[2] = texture_pos + ivec3(OCT_RES, OCT_RES - 1, 0); + copy_to[3] = texture_pos + ivec3(-1, OCT_RES, 0); + } else if (local == ivec2(0, OCT_RES - 1)) { + copy_to[1] = texture_pos + ivec3(-1, 0, 0); + copy_to[2] = texture_pos + ivec3(OCT_RES - 1, OCT_RES, 0); + copy_to[3] = texture_pos + ivec3(OCT_RES, -1, 0); + } else if (local == ivec2(OCT_RES - 1, OCT_RES - 1)) { + copy_to[1] = texture_pos + ivec3(0, OCT_RES, 0); + copy_to[2] = texture_pos + ivec3(OCT_RES, 0, 0); + copy_to[3] = texture_pos + ivec3(-1, -1, 0); + } else if (local.y == 0) { + copy_to[1] = texture_pos + ivec3(OCT_RES - local.x - 1, local.y - 1, 0); + } else if (local.x == 0) { + copy_to[1] = texture_pos + ivec3(local.x - 1, OCT_RES - local.y - 1, 0); + } else if (local.y == OCT_RES - 1) { + copy_to[1] = texture_pos + ivec3(OCT_RES - local.x - 1, local.y + 1, 0); + } else if (local.x == OCT_RES - 1) { + copy_to[1] = texture_pos + ivec3(local.x + 1, OCT_RES - local.y - 1, 0); + } + + for (int i = 0; i < 4; i++) { + if (copy_to[i] == ivec3(-2, -2, -2)) { + continue; + } +#ifdef MODE_IRRADIANCE + imageStore(irradiance_texture, copy_to[i], light_accum); +#endif +#ifdef MODE_DEPTH + imageStore(depth_texture, copy_to[i], vec4(depth_value, 0.0, 0.0)); +#endif + } + +#endif // MODE_STORE +} diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl new file mode 100644 index 0000000000..e4779aafaf --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_integrate.glsl @@ -0,0 +1,605 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +#define MAX_CASCADES 8 + +layout(set = 0, binding = 1) uniform texture3D sdf_cascades[MAX_CASCADES]; +layout(set = 0, binding = 2) uniform texture3D light_cascades[MAX_CASCADES]; +layout(set = 0, binding = 3) uniform texture3D aniso0_cascades[MAX_CASCADES]; +layout(set = 0, binding = 4) uniform texture3D aniso1_cascades[MAX_CASCADES]; + +layout(set = 0, binding = 6) uniform sampler linear_sampler; + +struct CascadeData { + vec3 offset; //offset of (0,0,0) in world coordinates + float to_cell; // 1/bounds * grid_size + ivec3 probe_world_offset; + uint pad; +}; + +layout(set = 0, binding = 7, std140) uniform Cascades { + CascadeData data[MAX_CASCADES]; +} +cascades; + +layout(r32ui, set = 0, binding = 8) uniform restrict uimage2DArray lightprobe_texture_data; +layout(rgba16i, set = 0, binding = 9) uniform restrict iimage2DArray lightprobe_history_texture; +layout(rgba32i, set = 0, binding = 10) uniform restrict iimage2D lightprobe_average_texture; + +//used for scrolling +layout(rgba16i, set = 0, binding = 11) uniform restrict iimage2DArray lightprobe_history_scroll_texture; +layout(rgba32i, set = 0, binding = 12) uniform restrict iimage2D lightprobe_average_scroll_texture; + +layout(rgba32i, set = 0, binding = 13) uniform restrict iimage2D lightprobe_average_parent_texture; + +layout(set = 1, binding = 0) uniform textureCube sky_irradiance; + +layout(set = 1, binding = 1) uniform sampler linear_sampler_mipmaps; + +#define HISTORY_BITS 10 + +#define SKY_MODE_DISABLED 0 +#define SKY_MODE_COLOR 1 +#define SKY_MODE_SKY 2 + +layout(push_constant, binding = 0, std430) uniform Params { + vec3 grid_size; + uint max_cascades; + + uint probe_axis_size; + uint cascade; + uint history_index; + uint history_size; + + uint ray_count; + float ray_bias; + ivec2 image_size; + + ivec3 world_offset; + uint sky_mode; + + ivec3 scroll; + float sky_energy; + + vec3 sky_color; + float y_mult; +} +params; + +const float PI = 3.14159265f; +const float GOLDEN_ANGLE = PI * (3.0 - sqrt(5.0)); + +vec3 vogel_hemisphere(uint p_index, uint p_count, float p_offset) { + float r = sqrt(float(p_index) + 0.5f) / sqrt(float(p_count)); + float theta = float(p_index) * GOLDEN_ANGLE + p_offset; + float y = cos(r * PI * 0.5); + float l = sin(r * PI * 0.5); + return vec3(l * cos(theta), l * sin(theta), y * (float(p_index & 1) * 2.0 - 1.0)); +} + +uvec3 hash3(uvec3 x) { + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = ((x >> 16) ^ x) * 0x45d9f3b; + x = (x >> 16) ^ x; + return x; +} + +float hashf3(vec3 co) { + return fract(sin(dot(co, vec3(12.9898, 78.233, 137.13451))) * 43758.5453); +} + +vec3 octahedron_encode(vec2 f) { + // https://twitter.com/Stubbesaurus/status/937994790553227264 + f = f * 2.0 - 1.0; + vec3 n = vec3(f.x, f.y, 1.0f - abs(f.x) - abs(f.y)); + float t = clamp(-n.z, 0.0, 1.0); + n.x += n.x >= 0 ? -t : t; + n.y += n.y >= 0 ? -t : t; + return normalize(n); +} + +uint rgbe_encode(vec3 color) { + const float pow2to9 = 512.0f; + const float B = 15.0f; + const float N = 9.0f; + const float LN2 = 0.6931471805599453094172321215; + + float cRed = clamp(color.r, 0.0, 65408.0); + float cGreen = clamp(color.g, 0.0, 65408.0); + float cBlue = clamp(color.b, 0.0, 65408.0); + + float cMax = max(cRed, max(cGreen, cBlue)); + + float expp = max(-B - 1.0f, floor(log(cMax) / LN2)) + 1.0f + B; + + float sMax = floor((cMax / pow(2.0f, expp - B - N)) + 0.5f); + + float exps = expp + 1.0f; + + if (0.0 <= sMax && sMax < pow2to9) { + exps = expp; + } + + float sRed = floor((cRed / pow(2.0f, exps - B - N)) + 0.5f); + float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f); + float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f); + return (uint(sRed) & 0x1FF) | ((uint(sGreen) & 0x1FF) << 9) | ((uint(sBlue) & 0x1FF) << 18) | ((uint(exps) & 0x1F) << 27); +} + +void main() { + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(pos, params.image_size))) { //too large, do nothing + return; + } + +#ifdef MODE_PROCESS + + float probe_cell_size = float(params.grid_size.x / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell; + + ivec3 probe_cell; + probe_cell.x = pos.x % int(params.probe_axis_size); + probe_cell.y = pos.y; + probe_cell.z = pos.x / int(params.probe_axis_size); + + vec3 probe_pos = cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size; + vec3 pos_to_uvw = 1.0 / params.grid_size; + + vec4 probe_sh_accum[SH_SIZE] = vec4[]( + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0) +#if (SH_SIZE == 16) + , + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0), + vec4(0.0) +#endif + ); + + // quickly ensure each probe has a different "offset" for the vogel function, based on integer world position + uvec3 h3 = hash3(uvec3(params.world_offset + probe_cell)); + float offset = hashf3(vec3(h3 & uvec3(0xFFFFF))); + + //for a more homogeneous hemisphere, alternate based on history frames + uint ray_offset = params.history_index; + uint ray_mult = params.history_size; + uint ray_total = ray_mult * params.ray_count; + + for (uint i = 0; i < params.ray_count; i++) { + vec3 ray_dir = vogel_hemisphere(ray_offset + i * ray_mult, ray_total, offset); + ray_dir.y *= params.y_mult; + ray_dir = normalize(ray_dir); + + //needs to be visible + vec3 ray_pos = probe_pos; + vec3 inv_dir = 1.0 / ray_dir; + + bool hit = false; + vec3 hit_normal; + vec3 hit_light; + vec3 hit_aniso0; + vec3 hit_aniso1; + + float bias = params.ray_bias; + vec3 abs_ray_dir = abs(ray_dir); + ray_pos += ray_dir * 1.0 / max(abs_ray_dir.x, max(abs_ray_dir.y, abs_ray_dir.z)) * bias / cascades.data[params.cascade].to_cell; + + for (uint j = params.cascade; j < params.max_cascades; j++) { + //convert to local bounds + vec3 pos = ray_pos - cascades.data[j].offset; + pos *= cascades.data[j].to_cell; + + if (any(lessThan(pos, vec3(0.0))) || any(greaterThanEqual(pos, params.grid_size))) { + continue; //already past bounds for this cascade, goto next + } + + //find maximum advance distance (until reaching bounds) + vec3 t0 = -pos * inv_dir; + vec3 t1 = (params.grid_size - pos) * inv_dir; + vec3 tmax = max(t0, t1); + float max_advance = min(tmax.x, min(tmax.y, tmax.z)); + + float advance = 0.0; + + vec3 uvw; + + while (advance < max_advance) { + //read how much to advance from SDF + uvw = (pos + ray_dir * advance) * pos_to_uvw; + + float distance = texture(sampler3D(sdf_cascades[j], linear_sampler), uvw).r * 255.0 - 1.0; + if (distance < 0.001) { + //consider hit + hit = true; + break; + } + + advance += distance; + } + + if (hit) { + const float EPSILON = 0.001; + hit_normal = normalize(vec3( + texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(EPSILON, 0.0, 0.0)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(EPSILON, 0.0, 0.0)).r, + texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(0.0, EPSILON, 0.0)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(0.0, EPSILON, 0.0)).r, + texture(sampler3D(sdf_cascades[j], linear_sampler), uvw + vec3(0.0, 0.0, EPSILON)).r - texture(sampler3D(sdf_cascades[j], linear_sampler), uvw - vec3(0.0, 0.0, EPSILON)).r)); + + hit_light = texture(sampler3D(light_cascades[j], linear_sampler), uvw).rgb; + vec4 aniso0 = texture(sampler3D(aniso0_cascades[j], linear_sampler), uvw); + hit_aniso0 = aniso0.rgb; + hit_aniso1 = vec3(aniso0.a, texture(sampler3D(aniso1_cascades[j], linear_sampler), uvw).rg); + + break; + } + + //change ray origin to collision with bounds + pos += ray_dir * max_advance; + pos /= cascades.data[j].to_cell; + pos += cascades.data[j].offset; + ray_pos = pos; + } + + vec4 light; + if (hit) { + //one liner magic + light.rgb = hit_light * (dot(max(vec3(0.0), (hit_normal * hit_aniso0)), vec3(1.0)) + dot(max(vec3(0.0), (-hit_normal * hit_aniso1)), vec3(1.0))); + light.a = 1.0; + } else if (params.sky_mode == SKY_MODE_SKY) { + light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; //use second mipmap because we dont usually throw a lot of rays, so this compensates + light.rgb *= params.sky_energy; + light.a = 0.0; + + } else if (params.sky_mode == SKY_MODE_COLOR) { + light.rgb = params.sky_color; + light.rgb *= params.sky_energy; + light.a = 0.0; + } else { + light = vec4(0, 0, 0, 0); + } + + vec3 ray_dir2 = ray_dir * ray_dir; + float c[SH_SIZE] = float[]( + + 0.282095, //l0 + 0.488603 * ray_dir.y, //l1n1 + 0.488603 * ray_dir.z, //l1n0 + 0.488603 * ray_dir.x, //l1p1 + 1.092548 * ray_dir.x * ray_dir.y, //l2n2 + 1.092548 * ray_dir.y * ray_dir.z, //l2n1 + 0.315392 * (3.0 * ray_dir2.z - 1.0), //l20 + 1.092548 * ray_dir.x * ray_dir.z, //l2p1 + 0.546274 * (ray_dir2.x - ray_dir2.y) //l2p2 +#if (SH_SIZE == 16) + , + 0.590043 * ray_dir.y * (3.0f * ray_dir2.x - ray_dir2.y), + 2.890611 * ray_dir.y * ray_dir.x * ray_dir.z, + 0.646360 * ray_dir.y * (-1.0f + 5.0f * ray_dir2.z), + 0.373176 * (5.0f * ray_dir2.z * ray_dir.z - 3.0f * ray_dir.z), + 0.457045 * ray_dir.x * (-1.0f + 5.0f * ray_dir2.z), + 1.445305 * (ray_dir2.x - ray_dir2.y) * ray_dir.z, + 0.590043 * ray_dir.x * (ray_dir2.x - 3.0f * ray_dir2.y) + +#endif + ); + + for (uint j = 0; j < SH_SIZE; j++) { + probe_sh_accum[j] += light * c[j]; + } + } + + for (uint i = 0; i < SH_SIZE; i++) { + // store in history texture + ivec3 prev_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(params.history_index)); + ivec2 average_pos = prev_pos.xy; + + vec4 value = probe_sh_accum[i] * 4.0 / float(params.ray_count); + + ivec4 ivalue = clamp(ivec4(value * float(1 << HISTORY_BITS)), -32768, 32767); //clamp to 16 bits, so higher values don't break average + + ivec4 prev_value = imageLoad(lightprobe_history_texture, prev_pos); + ivec4 average = imageLoad(lightprobe_average_texture, average_pos); + + average -= prev_value; + average += ivalue; + + imageStore(lightprobe_history_texture, prev_pos, ivalue); + imageStore(lightprobe_average_texture, average_pos, average); + } +#endif // MODE PROCESS + +#ifdef MODE_STORE + + // converting to octahedral in this step is requiered because + // octahedral is much faster to read from the screen than spherical harmonics, + // despite the very slight quality loss + + ivec2 sh_pos = (pos / OCT_SIZE) * ivec2(1, SH_SIZE); + ivec2 oct_pos = (pos / OCT_SIZE) * (OCT_SIZE + 2) + ivec2(1); + ivec2 local_pos = pos % OCT_SIZE; + + //fill the spherical harmonic + vec4 sh[SH_SIZE]; + + for (uint i = 0; i < SH_SIZE; i++) { + // store in history texture + ivec2 average_pos = sh_pos + ivec2(0, i); + ivec4 average = imageLoad(lightprobe_average_texture, average_pos); + + sh[i] = (vec4(average) / float(params.history_size)) / float(1 << HISTORY_BITS); + } + + //compute the octahedral normal for this texel + vec3 normal = octahedron_encode(vec2(local_pos) / float(OCT_SIZE)); + /* + // read the spherical harmonic + const float c1 = 0.429043; + const float c2 = 0.511664; + const float c3 = 0.743125; + const float c4 = 0.886227; + const float c5 = 0.247708; + vec4 light = (c1 * sh[8] * (normal.x * normal.x - normal.y * normal.y) + + c3 * sh[6] * normal.z * normal.z + + c4 * sh[0] - + c5 * sh[6] + + 2.0 * c1 * sh[4] * normal.x * normal.y + + 2.0 * c1 * sh[7] * normal.x * normal.z + + 2.0 * c1 * sh[5] * normal.y * normal.z + + 2.0 * c2 * sh[3] * normal.x + + 2.0 * c2 * sh[1] * normal.y + + 2.0 * c2 * sh[2] * normal.z); +*/ + vec3 normal2 = normal * normal; + float c[SH_SIZE] = float[]( + + 0.282095, //l0 + 0.488603 * normal.y, //l1n1 + 0.488603 * normal.z, //l1n0 + 0.488603 * normal.x, //l1p1 + 1.092548 * normal.x * normal.y, //l2n2 + 1.092548 * normal.y * normal.z, //l2n1 + 0.315392 * (3.0 * normal2.z - 1.0), //l20 + 1.092548 * normal.x * normal.z, //l2p1 + 0.546274 * (normal2.x - normal2.y) //l2p2 +#if (SH_SIZE == 16) + , + 0.590043 * normal.y * (3.0f * normal2.x - normal2.y), + 2.890611 * normal.y * normal.x * normal.z, + 0.646360 * normal.y * (-1.0f + 5.0f * normal2.z), + 0.373176 * (5.0f * normal2.z * normal.z - 3.0f * normal.z), + 0.457045 * normal.x * (-1.0f + 5.0f * normal2.z), + 1.445305 * (normal2.x - normal2.y) * normal.z, + 0.590043 * normal.x * (normal2.x - 3.0f * normal2.y) + +#endif + ); + + const float l_mult[SH_SIZE] = float[]( + 1.0, + 2.0 / 3.0, + 2.0 / 3.0, + 2.0 / 3.0, + 1.0 / 4.0, + 1.0 / 4.0, + 1.0 / 4.0, + 1.0 / 4.0, + 1.0 / 4.0 +#if (SH_SIZE == 16) + , // l4 does not contribute to irradiance + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 +#endif + ); + + vec3 irradiance = vec3(0.0); + vec3 radiance = vec3(0.0); + + for (uint i = 0; i < SH_SIZE; i++) { + vec3 m = sh[i].rgb * c[i] * 4.0; + irradiance += m * l_mult[i]; + radiance += m; + } + + //encode RGBE9995 for the final texture + + uint irradiance_rgbe = rgbe_encode(irradiance); + uint radiance_rgbe = rgbe_encode(radiance); + + //store in octahedral map + + ivec3 texture_pos = ivec3(oct_pos, int(params.cascade)); + ivec3 copy_to[4] = ivec3[](ivec3(-2, -2, -2), ivec3(-2, -2, -2), ivec3(-2, -2, -2), ivec3(-2, -2, -2)); + copy_to[0] = texture_pos + ivec3(local_pos, 0); + + if (local_pos == ivec2(0, 0)) { + copy_to[1] = texture_pos + ivec3(OCT_SIZE - 1, -1, 0); + copy_to[2] = texture_pos + ivec3(-1, OCT_SIZE - 1, 0); + copy_to[3] = texture_pos + ivec3(OCT_SIZE, OCT_SIZE, 0); + } else if (local_pos == ivec2(OCT_SIZE - 1, 0)) { + copy_to[1] = texture_pos + ivec3(0, -1, 0); + copy_to[2] = texture_pos + ivec3(OCT_SIZE, OCT_SIZE - 1, 0); + copy_to[3] = texture_pos + ivec3(-1, OCT_SIZE, 0); + } else if (local_pos == ivec2(0, OCT_SIZE - 1)) { + copy_to[1] = texture_pos + ivec3(-1, 0, 0); + copy_to[2] = texture_pos + ivec3(OCT_SIZE - 1, OCT_SIZE, 0); + copy_to[3] = texture_pos + ivec3(OCT_SIZE, -1, 0); + } else if (local_pos == ivec2(OCT_SIZE - 1, OCT_SIZE - 1)) { + copy_to[1] = texture_pos + ivec3(0, OCT_SIZE, 0); + copy_to[2] = texture_pos + ivec3(OCT_SIZE, 0, 0); + copy_to[3] = texture_pos + ivec3(-1, -1, 0); + } else if (local_pos.y == 0) { + copy_to[1] = texture_pos + ivec3(OCT_SIZE - local_pos.x - 1, local_pos.y - 1, 0); + } else if (local_pos.x == 0) { + copy_to[1] = texture_pos + ivec3(local_pos.x - 1, OCT_SIZE - local_pos.y - 1, 0); + } else if (local_pos.y == OCT_SIZE - 1) { + copy_to[1] = texture_pos + ivec3(OCT_SIZE - local_pos.x - 1, local_pos.y + 1, 0); + } else if (local_pos.x == OCT_SIZE - 1) { + copy_to[1] = texture_pos + ivec3(local_pos.x + 1, OCT_SIZE - local_pos.y - 1, 0); + } + + for (int i = 0; i < 4; i++) { + if (copy_to[i] == ivec3(-2, -2, -2)) { + continue; + } + imageStore(lightprobe_texture_data, copy_to[i], uvec4(irradiance_rgbe)); + imageStore(lightprobe_texture_data, copy_to[i] + ivec3(0, 0, int(params.max_cascades)), uvec4(radiance_rgbe)); + } + +#endif + +#ifdef MODE_SCROLL + + ivec3 probe_cell; + probe_cell.x = pos.x % int(params.probe_axis_size); + probe_cell.y = pos.y; + probe_cell.z = pos.x / int(params.probe_axis_size); + + ivec3 read_probe = probe_cell - params.scroll; + + if (all(greaterThanEqual(read_probe, ivec3(0))) && all(lessThan(read_probe, ivec3(params.probe_axis_size)))) { + // can scroll + ivec2 tex_pos; + tex_pos = read_probe.xy; + tex_pos.x += read_probe.z * int(params.probe_axis_size); + + //scroll + for (uint j = 0; j < params.history_size; j++) { + for (int i = 0; i < SH_SIZE; i++) { + // copy from history texture + ivec3 src_pos = ivec3(tex_pos.x, tex_pos.y * SH_SIZE + i, int(j)); + ivec3 dst_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(j)); + ivec4 value = imageLoad(lightprobe_history_texture, src_pos); + imageStore(lightprobe_history_scroll_texture, dst_pos, value); + } + } + + for (int i = 0; i < SH_SIZE; i++) { + // copy from average texture + ivec2 src_pos = ivec2(tex_pos.x, tex_pos.y * SH_SIZE + i); + ivec2 dst_pos = ivec2(pos.x, pos.y * SH_SIZE + i); + ivec4 value = imageLoad(lightprobe_average_texture, src_pos); + imageStore(lightprobe_average_scroll_texture, dst_pos, value); + } + } else if (params.cascade < params.max_cascades - 1) { + //cant scroll, must look for position in parent cascade + + //to global coords + float probe_cell_size = float(params.grid_size.x / float(params.probe_axis_size - 1)) / cascades.data[params.cascade].to_cell; + vec3 probe_pos = cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size; + + //to parent local coords + probe_pos -= cascades.data[params.cascade + 1].offset; + probe_pos *= cascades.data[params.cascade + 1].to_cell; + probe_pos = probe_pos * float(params.probe_axis_size - 1) / float(params.grid_size.x); + + ivec3 probe_posi = ivec3(probe_pos); + //add up all light, no need to use occlusion here, since occlusion will do its work afterwards + + vec4 average_light[SH_SIZE] = vec4[](vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0) +#if (SH_SIZE == 16) + , + vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0) +#endif + ); + float total_weight = 0.0; + + for (int i = 0; i < 8; i++) { + ivec3 offset = probe_posi + ((ivec3(i) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1)); + + vec3 trilinear = vec3(1.0) - abs(probe_pos - vec3(offset)); + float weight = trilinear.x * trilinear.y * trilinear.z; + + ivec2 tex_pos; + tex_pos = offset.xy; + tex_pos.x += offset.z * int(params.probe_axis_size); + + for (int j = 0; j < SH_SIZE; j++) { + // copy from history texture + ivec2 src_pos = ivec2(tex_pos.x, tex_pos.y * SH_SIZE + j); + ivec4 average = imageLoad(lightprobe_average_parent_texture, src_pos); + vec4 value = (vec4(average) / float(params.history_size)) / float(1 << HISTORY_BITS); + average_light[j] += value * weight; + } + + total_weight += weight; + } + + if (total_weight > 0.0) { + total_weight = 1.0 / total_weight; + } + //store the averaged values everywhere + + for (int i = 0; i < SH_SIZE; i++) { + ivec4 ivalue = clamp(ivec4(average_light[i] * total_weight * float(1 << HISTORY_BITS)), ivec4(-32768), ivec4(32767)); //clamp to 16 bits, so higher values don't break average + // copy from history texture + ivec3 dst_pos = ivec3(pos.x, pos.y * SH_SIZE + i, 0); + for (uint j = 0; j < params.history_size; j++) { + dst_pos.z = int(j); + imageStore(lightprobe_history_scroll_texture, dst_pos, ivalue); + } + + ivalue *= int(params.history_size); //average needs to have all history added up + imageStore(lightprobe_average_scroll_texture, dst_pos.xy, ivalue); + } + + } else { + // clear and let it re-raytrace, only for the last cascade, which happens very un-often + //scroll + for (uint j = 0; j < params.history_size; j++) { + for (int i = 0; i < SH_SIZE; i++) { + // copy from history texture + ivec3 dst_pos = ivec3(pos.x, pos.y * SH_SIZE + i, int(j)); + imageStore(lightprobe_history_scroll_texture, dst_pos, ivec4(0)); + } + } + + for (int i = 0; i < SH_SIZE; i++) { + // copy from average texture + ivec2 dst_pos = ivec2(pos.x, pos.y * SH_SIZE + i); + imageStore(lightprobe_average_scroll_texture, dst_pos, ivec4(0)); + } + } + +#endif + +#ifdef MODE_SCROLL_STORE + + //do not update probe texture, as these will be updated later + + for (uint j = 0; j < params.history_size; j++) { + for (int i = 0; i < SH_SIZE; i++) { + // copy from history texture + ivec3 spos = ivec3(pos.x, pos.y * SH_SIZE + i, int(j)); + ivec4 value = imageLoad(lightprobe_history_scroll_texture, spos); + imageStore(lightprobe_history_texture, spos, value); + } + } + + for (int i = 0; i < SH_SIZE; i++) { + // copy from average texture + ivec2 spos = ivec2(pos.x, pos.y * SH_SIZE + i); + ivec4 average = imageLoad(lightprobe_average_scroll_texture, spos); + imageStore(lightprobe_average_texture, spos, average); + } + +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl new file mode 100644 index 0000000000..d7d19897e3 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/sdfgi_preprocess.glsl @@ -0,0 +1,1056 @@ +#[compute] + +#version 450 + +VERSION_DEFINES + +#ifdef MODE_JUMPFLOOD_OPTIMIZED +#define GROUP_SIZE 8 + +layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = GROUP_SIZE) in; + +#elif defined(MODE_OCCLUSION) || defined(MODE_SCROLL) +//buffer layout +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; + +#else +//grid layout +layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; + +#endif + +#if defined(MODE_INITIALIZE_JUMP_FLOOD) || defined(MODE_INITIALIZE_JUMP_FLOOD_HALF) +layout(r16ui, set = 0, binding = 1) uniform restrict readonly uimage3D src_color; +layout(rgba8ui, set = 0, binding = 2) uniform restrict writeonly uimage3D dst_positions; +#endif + +#ifdef MODE_UPSCALE_JUMP_FLOOD +layout(r16ui, set = 0, binding = 1) uniform restrict readonly uimage3D src_color; +layout(rgba8ui, set = 0, binding = 2) uniform restrict readonly uimage3D src_positions_half; +layout(rgba8ui, set = 0, binding = 3) uniform restrict writeonly uimage3D dst_positions; +#endif + +#if defined(MODE_JUMPFLOOD) || defined(MODE_JUMPFLOOD_OPTIMIZED) +layout(rgba8ui, set = 0, binding = 1) uniform restrict readonly uimage3D src_positions; +layout(rgba8ui, set = 0, binding = 2) uniform restrict writeonly uimage3D dst_positions; +#endif + +#ifdef MODE_JUMPFLOOD_OPTIMIZED + +shared uvec4 group_positions[(GROUP_SIZE + 2) * (GROUP_SIZE + 2) * (GROUP_SIZE + 2)]; //4x4x4 with margins + +void group_store(ivec3 p_pos, uvec4 p_value) { + uint offset = uint(p_pos.z * (GROUP_SIZE + 2) * (GROUP_SIZE + 2) + p_pos.y * (GROUP_SIZE + 2) + p_pos.x); + group_positions[offset] = p_value; +} + +uvec4 group_load(ivec3 p_pos) { + uint offset = uint(p_pos.z * (GROUP_SIZE + 2) * (GROUP_SIZE + 2) + p_pos.y * (GROUP_SIZE + 2) + p_pos.x); + return group_positions[offset]; +} + +#endif + +#ifdef MODE_OCCLUSION + +layout(r16ui, set = 0, binding = 1) uniform restrict readonly uimage3D src_color; +layout(r8, set = 0, binding = 2) uniform restrict image3D dst_occlusion[8]; +layout(r32ui, set = 0, binding = 3) uniform restrict readonly uimage3D src_facing; + +const uvec2 group_size_offset[11] = uvec2[](uvec2(1, 0), uvec2(3, 1), uvec2(6, 4), uvec2(10, 10), uvec2(15, 20), uvec2(21, 35), uvec2(28, 56), uvec2(36, 84), uvec2(42, 120), uvec2(46, 162), uvec2(48, 208)); +const uint group_pos[256] = uint[](0, + 65536, 256, 1, + 131072, 65792, 512, 65537, 257, 2, + 196608, 131328, 66048, 768, 131073, 65793, 513, 65538, 258, 3, + 262144, 196864, 131584, 66304, 1024, 196609, 131329, 66049, 769, 131074, 65794, 514, 65539, 259, 4, + 327680, 262400, 197120, 131840, 66560, 1280, 262145, 196865, 131585, 66305, 1025, 196610, 131330, 66050, 770, 131075, 65795, 515, 65540, 260, 5, + 393216, 327936, 262656, 197376, 132096, 66816, 1536, 327681, 262401, 197121, 131841, 66561, 1281, 262146, 196866, 131586, 66306, 1026, 196611, 131331, 66051, 771, 131076, 65796, 516, 65541, 261, 6, + 458752, 393472, 328192, 262912, 197632, 132352, 67072, 1792, 393217, 327937, 262657, 197377, 132097, 66817, 1537, 327682, 262402, 197122, 131842, 66562, 1282, 262147, 196867, 131587, 66307, 1027, 196612, 131332, 66052, 772, 131077, 65797, 517, 65542, 262, 7, + 459008, 393728, 328448, 263168, 197888, 132608, 67328, 458753, 393473, 328193, 262913, 197633, 132353, 67073, 1793, 393218, 327938, 262658, 197378, 132098, 66818, 1538, 327683, 262403, 197123, 131843, 66563, 1283, 262148, 196868, 131588, 66308, 1028, 196613, 131333, 66053, 773, 131078, 65798, 518, 65543, 263, + 459264, 393984, 328704, 263424, 198144, 132864, 459009, 393729, 328449, 263169, 197889, 132609, 67329, 458754, 393474, 328194, 262914, 197634, 132354, 67074, 1794, 393219, 327939, 262659, 197379, 132099, 66819, 1539, 327684, 262404, 197124, 131844, 66564, 1284, 262149, 196869, 131589, 66309, 1029, 196614, 131334, 66054, 774, 131079, 65799, 519, + 459520, 394240, 328960, 263680, 198400, 459265, 393985, 328705, 263425, 198145, 132865, 459010, 393730, 328450, 263170, 197890, 132610, 67330, 458755, 393475, 328195, 262915, 197635, 132355, 67075, 1795, 393220, 327940, 262660, 197380, 132100, 66820, 1540, 327685, 262405, 197125, 131845, 66565, 1285, 262150, 196870, 131590, 66310, 1030, 196615, 131335, 66055, 775); + +shared uint occlusion_facing[((OCCLUSION_SIZE * 2) * (OCCLUSION_SIZE * 2) * (OCCLUSION_SIZE * 2)) / 4]; + +uint get_facing(ivec3 p_pos) { + uint ofs = uint(p_pos.z * OCCLUSION_SIZE * 2 * OCCLUSION_SIZE * 2 + p_pos.y * OCCLUSION_SIZE * 2 + p_pos.x); + uint v = occlusion_facing[ofs / 4]; + return (v >> ((ofs % 4) * 8)) & 0xFF; +} + +#endif + +#ifdef MODE_STORE + +layout(rgba8ui, set = 0, binding = 1) uniform restrict readonly uimage3D src_positions; +layout(r16ui, set = 0, binding = 2) uniform restrict readonly uimage3D src_albedo; +layout(r8, set = 0, binding = 3) uniform restrict readonly image3D src_occlusion[8]; +layout(r32ui, set = 0, binding = 4) uniform restrict readonly uimage3D src_light; +layout(r32ui, set = 0, binding = 5) uniform restrict readonly uimage3D src_light_aniso; +layout(r32ui, set = 0, binding = 6) uniform restrict readonly uimage3D src_facing; + +layout(r8, set = 0, binding = 7) uniform restrict writeonly image3D dst_sdf; +layout(r16ui, set = 0, binding = 8) uniform restrict writeonly uimage3D dst_occlusion; + +layout(set = 0, binding = 10, std430) restrict buffer DispatchData { + uint x; + uint y; + uint z; + uint total_count; +} +dispatch_data; + +struct ProcessVoxel { + uint position; //xyz 7 bit packed, extra 11 bits for neigbours + uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbous + uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours + //total neighbours: 26 +}; + +layout(set = 0, binding = 11, std430) restrict buffer writeonly ProcessVoxels { + ProcessVoxel data[]; +} +dst_process_voxels; + +shared ProcessVoxel store_positions[4 * 4 * 4]; +shared uint store_position_count; +shared uint store_from_index; +#endif + +#ifdef MODE_SCROLL + +layout(r16ui, set = 0, binding = 1) uniform restrict writeonly uimage3D dst_albedo; +layout(r32ui, set = 0, binding = 2) uniform restrict writeonly uimage3D dst_facing; +layout(r32ui, set = 0, binding = 3) uniform restrict writeonly uimage3D dst_light; +layout(r32ui, set = 0, binding = 4) uniform restrict writeonly uimage3D dst_light_aniso; + +layout(set = 0, binding = 5, std430) restrict buffer readonly DispatchData { + uint x; + uint y; + uint z; + uint total_count; +} +dispatch_data; + +struct ProcessVoxel { + uint position; //xyz 7 bit packed, extra 11 bits for neigbours + uint albedo; //rgb bits 0-15 albedo, bits 16-21 are normal bits (set if geometry exists toward that side), extra 11 bits for neibhbours + uint light; //rgbe8985 encoded total saved light, extra 2 bits for neighbous + uint light_aniso; //55555 light anisotropy, extra 2 bits for neighbours + //total neighbours: 26 +}; + +layout(set = 0, binding = 6, std430) restrict buffer readonly ProcessVoxels { + ProcessVoxel data[]; +} +src_process_voxels; + +#endif + +#ifdef MODE_SCROLL_OCCLUSION + +layout(r8, set = 0, binding = 1) uniform restrict image3D dst_occlusion[8]; +layout(r16ui, set = 0, binding = 2) uniform restrict readonly uimage3D src_occlusion; + +#endif + +layout(push_constant, binding = 0, std430) uniform Params { + ivec3 scroll; + + int grid_size; + + ivec3 probe_offset; + int step_size; + + bool half_size; + uint occlusion_index; + int cascade; + uint pad; +} +params; + +void main() { +#ifdef MODE_SCROLL + + // Pixel being shaded + int index = int(gl_GlobalInvocationID.x); + if (index >= dispatch_data.total_count) { //too big + return; + } + + ivec3 read_pos = (ivec3(src_process_voxels.data[index].position) >> ivec3(0, 7, 14)) & ivec3(0x7F); + ivec3 write_pos = read_pos + params.scroll; + + if (any(lessThan(write_pos, ivec3(0))) || any(greaterThanEqual(write_pos, ivec3(params.grid_size)))) { + return; //fits outside the 3D texture, dont do anything + } + + uint albedo = ((src_process_voxels.data[index].albedo & 0x7FFF) << 1) | 1; //add solid bit + imageStore(dst_albedo, write_pos, uvec4(albedo)); + + uint facing = (src_process_voxels.data[index].albedo >> 15) & 0x3F; //6 anisotropic facing bits + imageStore(dst_facing, write_pos, uvec4(facing)); + + uint light = src_process_voxels.data[index].light & 0x3fffffff; //30 bits of RGBE8985 + imageStore(dst_light, write_pos, uvec4(light)); + + uint light_aniso = src_process_voxels.data[index].light_aniso & 0x3fffffff; //30 bits of 6 anisotropic 5 bits values + imageStore(dst_light_aniso, write_pos, uvec4(light_aniso)); + +#endif + +#ifdef MODE_SCROLL_OCCLUSION + + ivec3 pos = ivec3(gl_GlobalInvocationID.xyz); + if (any(greaterThanEqual(pos, ivec3(params.grid_size) - abs(params.scroll)))) { //too large, do nothing + return; + } + + ivec3 read_pos = pos + max(ivec3(0), -params.scroll); + ivec3 write_pos = pos + max(ivec3(0), params.scroll); + + read_pos.z += params.cascade * params.grid_size; + uint occlusion = imageLoad(src_occlusion, read_pos).r; + read_pos.x += params.grid_size; + occlusion |= imageLoad(src_occlusion, read_pos).r << 16; + + const uint occlusion_shift[8] = uint[](12, 8, 4, 0, 28, 24, 20, 16); + + for (uint i = 0; i < 8; i++) { + float o = float((occlusion >> occlusion_shift[i]) & 0xF) / 15.0; + imageStore(dst_occlusion[i], write_pos, vec4(o)); + } + +#endif + +#ifdef MODE_INITIALIZE_JUMP_FLOOD + + ivec3 pos = ivec3(gl_GlobalInvocationID.xyz); + + uint c = imageLoad(src_color, pos).r; + uvec4 v; + if (bool(c & 0x1)) { + //bit set means this is solid + v.xyz = uvec3(pos); + v.w = 255; //not zero means used + } else { + v.xyz = uvec3(0); + v.w = 0; // zero means unused + } + + imageStore(dst_positions, pos, v); +#endif + +#ifdef MODE_INITIALIZE_JUMP_FLOOD_HALF + + ivec3 pos = ivec3(gl_GlobalInvocationID.xyz); + ivec3 base_pos = pos * 2; + + //since we store in half size, lets kind of randomize what we store, so + //the half size jump flood has a bit better chance to find something + uvec4 closest[8]; + int closest_count = 0; + + for (uint i = 0; i < 8; i++) { + ivec3 src_pos = base_pos + ((ivec3(i) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1)); + uint c = imageLoad(src_color, src_pos).r; + if (bool(c & 1)) { + uvec4 v = uvec4(uvec3(src_pos), 255); + closest[closest_count] = v; + closest_count++; + } + } + + if (closest_count == 0) { + imageStore(dst_positions, pos, uvec4(0)); + } else { + ivec3 indexv = (pos & ivec3(1, 1, 1)) * ivec3(1, 2, 4); + int index = (indexv.x | indexv.y | indexv.z) % closest_count; + imageStore(dst_positions, pos, closest[index]); + } + +#endif + +#ifdef MODE_JUMPFLOOD + + //regular jumpflood, efficent for large steps, inefficient for small steps + ivec3 pos = ivec3(gl_GlobalInvocationID.xyz); + + vec3 posf = vec3(pos); + + if (params.half_size) { + posf = posf * 2.0 + 0.5; + } + + uvec4 p = imageLoad(src_positions, pos); + + if (!params.half_size && p == uvec4(uvec3(pos), 255)) { + imageStore(dst_positions, pos, p); + return; //points to itself and valid, nothing better can be done, just pass + } + + float p_dist; + + if (p.w != 0) { + p_dist = distance(posf, vec3(p.xyz)); + } else { + p_dist = 0.0; //should not matter + } + + const uint offset_count = 26; + const ivec3 offsets[offset_count] = ivec3[]( + ivec3(-1, -1, -1), + ivec3(-1, -1, 0), + ivec3(-1, -1, 1), + ivec3(-1, 0, -1), + ivec3(-1, 0, 0), + ivec3(-1, 0, 1), + ivec3(-1, 1, -1), + ivec3(-1, 1, 0), + ivec3(-1, 1, 1), + ivec3(0, -1, -1), + ivec3(0, -1, 0), + ivec3(0, -1, 1), + ivec3(0, 0, -1), + ivec3(0, 0, 1), + ivec3(0, 1, -1), + ivec3(0, 1, 0), + ivec3(0, 1, 1), + ivec3(1, -1, -1), + ivec3(1, -1, 0), + ivec3(1, -1, 1), + ivec3(1, 0, -1), + ivec3(1, 0, 0), + ivec3(1, 0, 1), + ivec3(1, 1, -1), + ivec3(1, 1, 0), + ivec3(1, 1, 1)); + + for (uint i = 0; i < offset_count; i++) { + ivec3 ofs = pos + offsets[i] * params.step_size; + if (any(lessThan(ofs, ivec3(0))) || any(greaterThanEqual(ofs, ivec3(params.grid_size)))) { + continue; + } + uvec4 q = imageLoad(src_positions, ofs); + + if (q.w == 0) { + continue; //was not initialized yet, ignore + } + + float q_dist = distance(posf, vec3(p.xyz)); + if (p.w == 0 || q_dist < p_dist) { + p = q; //just replace because current is unused + p_dist = q_dist; + } + } + + imageStore(dst_positions, pos, p); +#endif + +#ifdef MODE_JUMPFLOOD_OPTIMIZED + //optimized version using shared compute memory + + ivec3 group_offset = ivec3(gl_WorkGroupID.xyz) % params.step_size; + ivec3 group_pos = group_offset + (ivec3(gl_WorkGroupID.xyz) / params.step_size) * ivec3(GROUP_SIZE * params.step_size); + + //load data into local group memory + + if (all(lessThan(ivec3(gl_LocalInvocationID.xyz), ivec3((GROUP_SIZE + 2) / 2)))) { + //use this thread for loading, this method uses less threads for this but its simpler and less divergent + ivec3 base_pos = ivec3(gl_LocalInvocationID.xyz) * 2; + for (uint i = 0; i < 8; i++) { + ivec3 load_pos = base_pos + ((ivec3(i) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1)); + ivec3 load_global_pos = group_pos + (load_pos - ivec3(1)) * params.step_size; + uvec4 q; + if (all(greaterThanEqual(load_global_pos, ivec3(0))) && all(lessThan(load_global_pos, ivec3(params.grid_size)))) { + q = imageLoad(src_positions, load_global_pos); + } else { + q = uvec4(0); //unused + } + + group_store(load_pos, q); + } + } + + ivec3 global_pos = group_pos + ivec3(gl_LocalInvocationID.xyz) * params.step_size; + + if (any(lessThan(global_pos, ivec3(0))) || any(greaterThanEqual(global_pos, ivec3(params.grid_size)))) { + return; //do nothing else, end here because outside range + } + + //sync + groupMemoryBarrier(); + barrier(); + + ivec3 local_pos = ivec3(gl_LocalInvocationID.xyz) + ivec3(1); + + const uint offset_count = 27; + const ivec3 offsets[offset_count] = ivec3[]( + ivec3(-1, -1, -1), + ivec3(-1, -1, 0), + ivec3(-1, -1, 1), + ivec3(-1, 0, -1), + ivec3(-1, 0, 0), + ivec3(-1, 0, 1), + ivec3(-1, 1, -1), + ivec3(-1, 1, 0), + ivec3(-1, 1, 1), + ivec3(0, -1, -1), + ivec3(0, -1, 0), + ivec3(0, -1, 1), + ivec3(0, 0, -1), + ivec3(0, 0, 0), + ivec3(0, 0, 1), + ivec3(0, 1, -1), + ivec3(0, 1, 0), + ivec3(0, 1, 1), + ivec3(1, -1, -1), + ivec3(1, -1, 0), + ivec3(1, -1, 1), + ivec3(1, 0, -1), + ivec3(1, 0, 0), + ivec3(1, 0, 1), + ivec3(1, 1, -1), + ivec3(1, 1, 0), + ivec3(1, 1, 1)); + + //only makes sense if point is inside screen + uvec4 closest = uvec4(0); + float closest_dist = 0.0; + + vec3 posf = vec3(global_pos); + + if (params.half_size) { + posf = posf * 2.0 + 0.5; + } + + for (uint i = 0; i < offset_count; i++) { + uvec4 point = group_load(local_pos + offsets[i]); + + if (point.w == 0) { + continue; //was not initialized yet, ignore + } + + float dist = distance(posf, vec3(point.xyz)); + if (closest.w == 0 || dist < closest_dist) { + closest = point; + closest_dist = dist; + } + } + + imageStore(dst_positions, global_pos, closest); + +#endif + +#ifdef MODE_UPSCALE_JUMP_FLOOD + + ivec3 pos = ivec3(gl_GlobalInvocationID.xyz); + + uint c = imageLoad(src_color, pos).r; + uvec4 v; + if (bool(c & 1)) { + //bit set means this is solid + v.xyz = uvec3(pos); + v.w = 255; //not zero means used + } else { + v = imageLoad(src_positions_half, pos >> 1); + float d = length(vec3(ivec3(v.xyz) - pos)); + + ivec3 vbase = ivec3(v.xyz - (v.xyz & uvec3(1))); + + //search around if there is a better candidate from the same block + for (int i = 0; i < 8; i++) { + ivec3 bits = ((ivec3(i) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1)); + ivec3 p = vbase + bits; + + float d2 = length(vec3(p - pos)); + if (d2 < d) { //check valid distance before test so we avoid a read + uint c2 = imageLoad(src_color, p).r; + if (bool(c2 & 1)) { + v.xyz = uvec3(p); + d = d2; + } + } + } + + //could validate better position.. + } + + imageStore(dst_positions, pos, v); + +#endif + +#ifdef MODE_OCCLUSION + + uint invocation_idx = uint(gl_LocalInvocationID.x); + ivec3 region = ivec3(gl_WorkGroupID); + + ivec3 region_offset = -ivec3(OCCLUSION_SIZE); + region_offset += region * OCCLUSION_SIZE * 2; + region_offset += params.probe_offset * OCCLUSION_SIZE; + + if (params.scroll != ivec3(0)) { + //validate scroll region + ivec3 region_offset_to = region_offset + ivec3(OCCLUSION_SIZE * 2); + uvec3 scroll_mask = uvec3(notEqual(params.scroll, ivec3(0))); //save which axes acre scrolling + ivec3 scroll_from = mix(ivec3(0), ivec3(params.grid_size) + params.scroll, lessThan(params.scroll, ivec3(0))); + ivec3 scroll_to = mix(ivec3(params.grid_size), params.scroll, greaterThan(params.scroll, ivec3(0))); + + if ((uvec3(lessThanEqual(region_offset_to, scroll_from)) | uvec3(greaterThanEqual(region_offset, scroll_to))) * scroll_mask == scroll_mask) { //all axes that scroll are out, exit + return; //region outside scroll bounds, quit + } + } + +#define OCC_HALF_SIZE (OCCLUSION_SIZE / 2) + + ivec3 local_ofs = ivec3(uvec3(invocation_idx % OCC_HALF_SIZE, (invocation_idx % (OCC_HALF_SIZE * OCC_HALF_SIZE)) / OCC_HALF_SIZE, invocation_idx / (OCC_HALF_SIZE * OCC_HALF_SIZE))) * 4; + + /* for(int i=0;i<64;i++) { + ivec3 offset = region_offset + local_ofs + ((ivec3(i) >> ivec3(0,2,4)) & ivec3(3,3,3)); + uint facig = + if (all(greaterThanEqual(offset,ivec3(0))) && all(lessThan(offset,ivec3(params.grid_size)))) {*/ + + for (int i = 0; i < 16; i++) { //skip x, so it can be packed + + ivec3 offset = local_ofs + ((ivec3(i * 4) >> ivec3(0, 2, 4)) & ivec3(3, 3, 3)); + + uint facing_pack = 0; + for (int j = 0; j < 4; j++) { + ivec3 foffset = region_offset + offset + ivec3(j, 0, 0); + if (all(greaterThanEqual(foffset, ivec3(0))) && all(lessThan(foffset, ivec3(params.grid_size)))) { + uint f = imageLoad(src_facing, foffset).r; + facing_pack |= f << (j * 8); + } + } + + occlusion_facing[(offset.z * (OCCLUSION_SIZE * 2 * OCCLUSION_SIZE * 2) + offset.y * (OCCLUSION_SIZE * 2) + offset.x) / 4] = facing_pack; + } + + //sync occlusion saved + groupMemoryBarrier(); + barrier(); + + //process occlusion + +#define OCC_STEPS (OCCLUSION_SIZE * 3 - 2) +#define OCC_HALF_STEPS (OCC_STEPS / 2) + + for (int step = 0; step < OCC_STEPS; step++) { + bool shrink = step >= OCC_HALF_STEPS; + int occ_step = shrink ? OCC_HALF_STEPS - (step - OCC_HALF_STEPS) - 1 : step; + + if (invocation_idx < group_size_offset[occ_step].x) { + uint pv = group_pos[group_size_offset[occ_step].y + invocation_idx]; + ivec3 proc_abs = (ivec3(int(pv)) >> ivec3(0, 8, 16)) & ivec3(0xFF); + + if (shrink) { + proc_abs = ivec3(OCCLUSION_SIZE) - proc_abs - ivec3(1); + } + + for (int i = 0; i < 8; i++) { + ivec3 bits = ((ivec3(i) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1)); + ivec3 proc_sign = bits * 2 - 1; + ivec3 local_offset = ivec3(OCCLUSION_SIZE) + proc_abs * proc_sign - (ivec3(1) - bits); + ivec3 offset = local_offset + region_offset; + if (all(greaterThanEqual(offset, ivec3(0))) && all(lessThan(offset, ivec3(params.grid_size)))) { + float occ; + + uint facing = get_facing(local_offset); + + if (facing != 0) { //solid + occ = 0.0; + } else if (step == 0) { +#if 0 + occ = 0.0; + if (get_facing(local_offset - ivec3(proc_sign.x,0,0))==0) { + occ+=1.0; + } + if (get_facing(local_offset - ivec3(0,proc_sign.y,0))==0) { + occ+=1.0; + } + if (get_facing(local_offset - ivec3(0,0,proc_sign.z))==0) { + occ+=1.0; + } + /* + if (get_facing(local_offset - proc_sign)==0) { + occ+=1.0; + }*/ + + occ/=3.0; +#endif + occ = 1.0; + + } else { + ivec3 read_dir = -proc_sign; + + ivec3 major_axis; + if (proc_abs.x < proc_abs.y) { + if (proc_abs.z < proc_abs.y) { + major_axis = ivec3(0, 1, 0); + } else { + major_axis = ivec3(0, 0, 1); + } + } else { + if (proc_abs.z < proc_abs.x) { + major_axis = ivec3(1, 0, 0); + } else { + major_axis = ivec3(0, 0, 1); + } + } + + float avg = 0.0; + occ = 0.0; + + ivec3 read_x = offset + ivec3(read_dir.x, 0, 0) + (proc_abs.x == 0 ? major_axis * read_dir : ivec3(0)); + ivec3 read_y = offset + ivec3(0, read_dir.y, 0) + (proc_abs.y == 0 ? major_axis * read_dir : ivec3(0)); + ivec3 read_z = offset + ivec3(0, 0, read_dir.z) + (proc_abs.z == 0 ? major_axis * read_dir : ivec3(0)); + + uint facing_x = get_facing(read_x - region_offset); + if (facing_x == 0) { + if (all(greaterThanEqual(read_x, ivec3(0))) && all(lessThan(read_x, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_x).r; + avg += 1.0; + } + } else { + if (proc_abs.x != 0) { //do not occlude from voxels in the opposite octant + avg += 1.0; + } + } + + uint facing_y = get_facing(read_y - region_offset); + if (facing_y == 0) { + if (all(greaterThanEqual(read_y, ivec3(0))) && all(lessThan(read_y, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_y).r; + avg += 1.0; + } + } else { + if (proc_abs.y != 0) { + avg += 1.0; + } + } + + uint facing_z = get_facing(read_z - region_offset); + if (facing_z == 0) { + if (all(greaterThanEqual(read_z, ivec3(0))) && all(lessThan(read_z, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_z).r; + avg += 1.0; + } + } else { + if (proc_abs.z != 0) { + avg += 1.0; + } + } + + if (avg > 0.0) { + occ /= avg; + } + } + + imageStore(dst_occlusion[params.occlusion_index], offset, vec4(occ)); + } + } + } + + groupMemoryBarrier(); + barrier(); + } +#if 1 + //bias solid voxels away + + for (int i = 0; i < 64; i++) { + ivec3 local_offset = local_ofs + ((ivec3(i) >> ivec3(0, 2, 4)) & ivec3(3, 3, 3)); + ivec3 offset = region_offset + local_offset; + + if (all(greaterThanEqual(offset, ivec3(0))) && all(lessThan(offset, ivec3(params.grid_size)))) { + uint facing = get_facing(local_offset); + + if (facing != 0) { + //only work on solids + + ivec3 proc_pos = local_offset - ivec3(OCCLUSION_SIZE); + proc_pos += mix(ivec3(0), ivec3(1), greaterThanEqual(proc_pos, ivec3(0))); + + float avg = 0.0; + float occ = 0.0; + + ivec3 read_dir = -sign(proc_pos); + ivec3 read_dir_x = ivec3(read_dir.x, 0, 0); + ivec3 read_dir_y = ivec3(0, read_dir.y, 0); + ivec3 read_dir_z = ivec3(0, 0, read_dir.z); + //solid +#if 0 + + uvec3 facing_pos_base = (uvec3(facing) >> uvec3(0,1,2)) & uvec3(1,1,1); + uvec3 facing_neg_base = (uvec3(facing) >> uvec3(3,4,5)) & uvec3(1,1,1); + uvec3 facing_pos= facing_pos_base &((~facing_neg_base)&uvec3(1,1,1)); + uvec3 facing_neg= facing_neg_base &((~facing_pos_base)&uvec3(1,1,1)); +#else + uvec3 facing_pos = (uvec3(facing) >> uvec3(0, 1, 2)) & uvec3(1, 1, 1); + uvec3 facing_neg = (uvec3(facing) >> uvec3(3, 4, 5)) & uvec3(1, 1, 1); +#endif + bvec3 read_valid = bvec3(mix(facing_neg, facing_pos, greaterThan(read_dir, ivec3(0)))); + + //sides + if (read_valid.x) { + ivec3 read_offset = local_offset + read_dir_x; + uint f = get_facing(read_offset); + if (f == 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_offset).r; + avg += 1.0; + } + } + } + + if (read_valid.y) { + ivec3 read_offset = local_offset + read_dir_y; + uint f = get_facing(read_offset); + if (f == 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_offset).r; + avg += 1.0; + } + } + } + + if (read_valid.z) { + ivec3 read_offset = local_offset + read_dir_z; + uint f = get_facing(read_offset); + if (f == 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_offset).r; + avg += 1.0; + } + } + } + + //adjacents + + if (all(read_valid.yz)) { + ivec3 read_offset = local_offset + read_dir_y + read_dir_z; + uint f = get_facing(read_offset); + if (f == 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_offset).r; + avg += 1.0; + } + } + } + + if (all(read_valid.xz)) { + ivec3 read_offset = local_offset + read_dir_x + read_dir_z; + uint f = get_facing(read_offset); + if (f == 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_offset).r; + avg += 1.0; + } + } + } + + if (all(read_valid.xy)) { + ivec3 read_offset = local_offset + read_dir_x + read_dir_y; + uint f = get_facing(read_offset); + if (f == 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_offset).r; + avg += 1.0; + } + } + } + + //diagonal + + if (all(read_valid)) { + ivec3 read_offset = local_offset + read_dir; + uint f = get_facing(read_offset); + if (f == 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occ += imageLoad(dst_occlusion[params.occlusion_index], read_offset).r; + avg += 1.0; + } + } + } + + if (avg > 0.0) { + occ /= avg; + } + + imageStore(dst_occlusion[params.occlusion_index], offset, vec4(occ)); + } + } + } + +#endif + +#if 1 + groupMemoryBarrier(); + barrier(); + + for (int i = 0; i < 64; i++) { + ivec3 local_offset = local_ofs + ((ivec3(i) >> ivec3(0, 2, 4)) & ivec3(3, 3, 3)); + ivec3 offset = region_offset + local_offset; + + if (all(greaterThanEqual(offset, ivec3(0))) && all(lessThan(offset, ivec3(params.grid_size)))) { + uint facing = get_facing(local_offset); + + if (facing == 0) { + ivec3 proc_pos = local_offset - ivec3(OCCLUSION_SIZE); + proc_pos += mix(ivec3(0), ivec3(1), greaterThanEqual(proc_pos, ivec3(0))); + + ivec3 proc_abs = abs(proc_pos); + + ivec3 read_dir = sign(proc_pos); //opposite direction + ivec3 read_dir_x = ivec3(read_dir.x, 0, 0); + ivec3 read_dir_y = ivec3(0, read_dir.y, 0); + ivec3 read_dir_z = ivec3(0, 0, read_dir.z); + //solid + uvec3 read_mask = mix(uvec3(1, 2, 4), uvec3(8, 16, 32), greaterThan(read_dir, ivec3(0))); //match positive with negative normals + uvec3 block_mask = mix(uvec3(1, 2, 4), uvec3(8, 16, 32), lessThan(read_dir, ivec3(0))); //match positive with negative normals + + block_mask = uvec3(0); + + float visible = 0.0; + float occlude_total = 0.0; + + if (proc_abs.x < OCCLUSION_SIZE) { + ivec3 read_offset = local_offset + read_dir_x; + uint x_mask = get_facing(read_offset); + if (x_mask != 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occlude_total += 1.0; + if (bool(x_mask & read_mask.x) && !bool(x_mask & block_mask.x)) { + visible += 1.0; + } + } + } + } + + if (proc_abs.y < OCCLUSION_SIZE) { + ivec3 read_offset = local_offset + read_dir_y; + uint y_mask = get_facing(read_offset); + if (y_mask != 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occlude_total += 1.0; + if (bool(y_mask & read_mask.y) && !bool(y_mask & block_mask.y)) { + visible += 1.0; + } + } + } + } + + if (proc_abs.z < OCCLUSION_SIZE) { + ivec3 read_offset = local_offset + read_dir_z; + uint z_mask = get_facing(read_offset); + if (z_mask != 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occlude_total += 1.0; + if (bool(z_mask & read_mask.z) && !bool(z_mask & block_mask.z)) { + visible += 1.0; + } + } + } + } + + //if near the cartesian plane, test in opposite direction too + + read_mask = mix(uvec3(1, 2, 4), uvec3(8, 16, 32), lessThan(read_dir, ivec3(0))); //match negative with positive normals + block_mask = mix(uvec3(1, 2, 4), uvec3(8, 16, 32), greaterThan(read_dir, ivec3(0))); //match negative with positive normals + block_mask = uvec3(0); + + if (proc_abs.x == 1) { + ivec3 read_offset = local_offset - read_dir_x; + uint x_mask = get_facing(read_offset); + if (x_mask != 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occlude_total += 1.0; + if (bool(x_mask & read_mask.x) && !bool(x_mask & block_mask.x)) { + visible += 1.0; + } + } + } + } + + if (proc_abs.y == 1) { + ivec3 read_offset = local_offset - read_dir_y; + uint y_mask = get_facing(read_offset); + if (y_mask != 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occlude_total += 1.0; + if (bool(y_mask & read_mask.y) && !bool(y_mask & block_mask.y)) { + visible += 1.0; + } + } + } + } + + if (proc_abs.z == 1) { + ivec3 read_offset = local_offset - read_dir_z; + uint z_mask = get_facing(read_offset); + if (z_mask != 0) { + read_offset += region_offset; + if (all(greaterThanEqual(read_offset, ivec3(0))) && all(lessThan(read_offset, ivec3(params.grid_size)))) { + occlude_total += 1.0; + if (bool(z_mask & read_mask.z) && !bool(z_mask & block_mask.z)) { + visible += 1.0; + } + } + } + } + + if (occlude_total > 0.0) { + float occ = imageLoad(dst_occlusion[params.occlusion_index], offset).r; + occ *= visible / occlude_total; + imageStore(dst_occlusion[params.occlusion_index], offset, vec4(occ)); + } + } + } + } + +#endif + + /* + for(int i=0;i<8;i++) { + ivec3 local_offset = local_pos + ((ivec3(i) >> ivec3(2,1,0)) & ivec3(1,1,1)) * OCCLUSION_SIZE; + ivec3 offset = local_offset - ivec3(OCCLUSION_SIZE); //looking around probe, so starts negative + offset += region * OCCLUSION_SIZE * 2; //offset by region + offset += params.probe_offset * OCCLUSION_SIZE; // offset by probe offset + if (all(greaterThanEqual(offset,ivec3(0))) && all(lessThan(offset,ivec3(params.grid_size)))) { + imageStore(dst_occlusion[params.occlusion_index],offset,vec4( occlusion_data[ to_linear(local_offset) ] )); + //imageStore(dst_occlusion[params.occlusion_index],offset,vec4( occlusion_solid[ to_linear(local_offset) ] )); + } + } +*/ + +#endif + +#ifdef MODE_STORE + + ivec3 local = ivec3(gl_LocalInvocationID.xyz); + ivec3 pos = ivec3(gl_GlobalInvocationID.xyz); + // store SDF + uvec4 p = imageLoad(src_positions, pos); + + bool solid = false; + float d; + if (ivec3(p.xyz) == pos) { + //solid block + d = 0; + solid = true; + } else { + //distance block + d = 1.0 + length(vec3(p.xyz) - vec3(pos)); + } + + d /= 255.0; + + imageStore(dst_sdf, pos, vec4(d)); + + // STORE OCCLUSION + + uint occlusion = 0; + const uint occlusion_shift[8] = uint[](12, 8, 4, 0, 28, 24, 20, 16); + for (int i = 0; i < 8; i++) { + float occ = imageLoad(src_occlusion[i], pos).r; + occlusion |= uint(clamp(occ * 15.0, 0.0, 15.0)) << occlusion_shift[i]; + } + { + ivec3 occ_pos = pos; + occ_pos.z += params.cascade * params.grid_size; + imageStore(dst_occlusion, occ_pos, uvec4(occlusion & 0xFFFF)); + occ_pos.x += params.grid_size; + imageStore(dst_occlusion, occ_pos, uvec4(occlusion >> 16)); + } + + // STORE POSITIONS + + if (local == ivec3(0)) { + store_position_count = 0; //base one stores as zero, the others wait + } + + groupMemoryBarrier(); + barrier(); + + if (solid) { + uint index = atomicAdd(store_position_count, 1); + // At least do the conversion work in parallel + store_positions[index].position = uint(pos.x | (pos.y << 7) | (pos.z << 14)); + + //see around which voxels point to this one, add them to the list + uint bit_index = 0; + uint neighbour_bits = 0; + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + for (int k = -1; k <= 1; k++) { + if (i == 0 && j == 0 && k == 0) { + continue; + } + ivec3 npos = pos + ivec3(i, j, k); + if (all(greaterThanEqual(npos, ivec3(0))) && all(lessThan(npos, ivec3(params.grid_size)))) { + p = imageLoad(src_positions, npos); + if (ivec3(p.xyz) == pos) { + neighbour_bits |= (1 << bit_index); + } + } + bit_index++; + } + } + } + + uint rgb = imageLoad(src_albedo, pos).r; + uint facing = imageLoad(src_facing, pos).r; + + store_positions[index].albedo = rgb >> 1; //store as it comes (555) to avoid precision loss (and move away the alpha bit) + store_positions[index].albedo |= (facing & 0x3F) << 15; // store facing in bits 15-21 + + store_positions[index].albedo |= neighbour_bits << 21; //store lower 11 bits of neighbours with remaining albedo + store_positions[index].position |= (neighbour_bits >> 11) << 21; //store 11 bits more of neighbours with position + + store_positions[index].light = imageLoad(src_light, pos).r; + store_positions[index].light_aniso = imageLoad(src_light_aniso, pos).r; + //add neighbours + store_positions[index].light |= (neighbour_bits >> 22) << 30; //store 2 bits more of neighbours with light + store_positions[index].light_aniso |= (neighbour_bits >> 24) << 30; //store 2 bits more of neighbours with aniso + } + + groupMemoryBarrier(); + barrier(); + + // global increment only once per group, to reduce pressure + + if (local == ivec3(0) && store_position_count > 0) { + store_from_index = atomicAdd(dispatch_data.total_count, store_position_count); + uint group_count = (store_from_index + store_position_count - 1) / 64 + 1; + atomicMax(dispatch_data.x, group_count); + } + + groupMemoryBarrier(); + barrier(); + + uint read_index = uint(local.z * 4 * 4 + local.y * 4 + local.x); + uint write_index = store_from_index + read_index; + + if (read_index < store_position_count) { + dst_process_voxels.data[write_index] = store_positions[read_index]; + } + + if (pos == ivec3(0)) { + //this thread clears y and z + dispatch_data.y = 1; + dispatch_data.z = 1; + } +#endif +} diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 55b65d2747..83cbfb85bd 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -212,10 +212,14 @@ RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p return render_pipeline_create(p_shader, p_framebuffer_format, p_vertex_format, p_render_primitive, rasterization_state, multisample_state, depth_stencil_state, color_blend_state, p_dynamic_state_flags); } -Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region) { +Vector<int64_t> RenderingDevice::_draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const TypedArray<RID> &p_storage_textures) { Vector<DrawListID> splits; splits.resize(p_splits); - draw_list_begin_split(p_framebuffer, p_splits, splits.ptrw(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region); + Vector<RID> stextures; + for (int i = 0; i < p_storage_textures.size(); i++) { + stextures.push_back(p_storage_textures[i]); + } + draw_list_begin_split(p_framebuffer, p_splits, splits.ptrw(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, stextures); Vector<int64_t> split_ids; split_ids.resize(splits.size()); @@ -236,6 +240,10 @@ void RenderingDevice::_compute_list_set_push_constant(ComputeListID p_list, cons compute_list_set_push_constant(p_list, p_data.ptr(), p_data_size); } +void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads, uint32_t p_x_local_group, uint32_t p_y_local_group, uint32_t p_z_local_group) { + compute_list_dispatch(p_list, (p_x_threads - 1) / p_x_local_group + 1, (p_y_threads - 1) / p_y_local_group + 1, (p_z_threads - 1) / p_z_local_group + 1); +} + void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_create", "format", "view", "data"), &RenderingDevice::_texture_create, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("texture_create_shared", "view", "with_texture"), &RenderingDevice::_texture_create_shared); @@ -254,8 +262,10 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("texture_resolve_multisample", "from_texture", "to_texture", "sync_with_draw"), &RenderingDevice::texture_resolve_multisample, DEFVAL(false)); ClassDB::bind_method(D_METHOD("framebuffer_format_create", "attachments"), &RenderingDevice::_framebuffer_format_create); + ClassDB::bind_method(D_METHOD("framebuffer_format_create_empty", "size"), &RenderingDevice::framebuffer_format_create_empty); ClassDB::bind_method(D_METHOD("framebuffer_format_get_texture_samples", "format"), &RenderingDevice::framebuffer_format_get_texture_samples); ClassDB::bind_method(D_METHOD("framebuffer_create", "textures", "validate_with_format"), &RenderingDevice::_framebuffer_create, DEFVAL(INVALID_FORMAT_ID)); + ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(INVALID_FORMAT_ID)); ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format); ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create); @@ -271,7 +281,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("shader_get_vertex_input_attribute_mask", "shader"), &RenderingDevice::shader_get_vertex_input_attribute_mask); ClassDB::bind_method(D_METHOD("uniform_buffer_create", "size_bytes", "data"), &RenderingDevice::uniform_buffer_create, DEFVAL(Vector<uint8_t>())); - ClassDB::bind_method(D_METHOD("storage_buffer_create", "size_bytes", "data"), &RenderingDevice::storage_buffer_create, DEFVAL(Vector<uint8_t>())); + ClassDB::bind_method(D_METHOD("storage_buffer_create", "size_bytes", "data", "usage"), &RenderingDevice::storage_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(0)); ClassDB::bind_method(D_METHOD("texture_buffer_create", "size_bytes", "format", "data"), &RenderingDevice::texture_buffer_create, DEFVAL(Vector<uint8_t>())); ClassDB::bind_method(D_METHOD("uniform_set_create", "uniforms", "shader", "shader_set"), &RenderingDevice::_uniform_set_create); @@ -292,8 +302,8 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_begin_for_screen", "screen", "clear_color"), &RenderingDevice::draw_list_begin_for_screen, DEFVAL(DisplayServer::MAIN_WINDOW_ID), DEFVAL(Color())); - ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i())); - ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i())); + ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>())); + ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2i()), DEFVAL(TypedArray<RID>())); ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline); ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set); @@ -625,6 +635,8 @@ void RenderingDevice::_bind_methods() { BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT16); BIND_ENUM_CONSTANT(INDEX_BUFFER_FORMAT_UINT32); + BIND_ENUM_CONSTANT(STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT); + BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER); //for sampling only (sampler GLSL type) BIND_ENUM_CONSTANT(UNIFORM_TYPE_SAMPLER_WITH_TEXTURE); // for sampling only); but includes a texture); (samplerXX GLSL type)); first a sampler then a texture BIND_ENUM_CONSTANT(UNIFORM_TYPE_TEXTURE); //only texture); (textureXX GLSL type) diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index ee39ee11ed..72afc7c621 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -467,9 +467,11 @@ public: // This ID is warranted to be unique for the same formats, does not need to be freed virtual FramebufferFormatID framebuffer_format_create(const Vector<AttachmentFormat> &p_format) = 0; + virtual FramebufferFormatID framebuffer_format_create_empty(const Size2i &p_size) = 0; virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0; virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0; + virtual RID framebuffer_create_empty(const Size2i &p_size, FramebufferFormatID p_format_check = INVALID_ID) = 0; virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0; @@ -618,8 +620,12 @@ public: UNIFORM_TYPE_MAX }; + enum StorageBufferUsage { + STORAGE_BUFFER_USAGE_DISPATCH_INDIRECT = 1 + }; + virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0; - virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0; + virtual RID storage_buffer_create(uint32_t p_size, const Vector<uint8_t> &p_data = Vector<uint8_t>(), uint32_t p_usage = 0) = 0; virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector<uint8_t> &p_data = Vector<uint8_t>()) = 0; struct Uniform { @@ -940,8 +946,8 @@ public: typedef int64_t DrawListID; virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()) = 0; - virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; - virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; + virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; + virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0; virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0; @@ -968,10 +974,14 @@ public: virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) = 0; virtual void compute_list_set_push_constant(ComputeListID p_list, const void *p_data, uint32_t p_data_size) = 0; virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) = 0; + virtual void compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads, uint32_t p_x_local_group, uint32_t p_y_local_group, uint32_t p_z_local_group); + virtual void compute_list_dispatch_indirect(ComputeListID p_list, RID p_buffer, uint32_t p_offset) = 0; virtual void compute_list_add_barrier(ComputeListID p_list) = 0; virtual void compute_list_end() = 0; + virtual void full_barrier() = 0; + /***************/ /**** FREE! ****/ /***************/ @@ -1070,7 +1080,7 @@ protected: RID _render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags = 0); - Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()); + Vector<int64_t> _draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const TypedArray<RID> &p_storage_textures = TypedArray<RID>()); void _draw_list_set_push_constant(DrawListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size); void _compute_list_set_push_constant(ComputeListID p_list, const Vector<uint8_t> &p_data, uint32_t p_data_size); }; @@ -1089,6 +1099,7 @@ VARIANT_ENUM_CAST(RenderingDevice::SamplerRepeatMode) VARIANT_ENUM_CAST(RenderingDevice::SamplerBorderColor) VARIANT_ENUM_CAST(RenderingDevice::VertexFrequency) VARIANT_ENUM_CAST(RenderingDevice::IndexBufferFormat) +VARIANT_ENUM_CAST(RenderingDevice::StorageBufferUsage) VARIANT_ENUM_CAST(RenderingDevice::UniformType) VARIANT_ENUM_CAST(RenderingDevice::RenderPrimitive) VARIANT_ENUM_CAST(RenderingDevice::PolygonCullMode) diff --git a/servers/rendering/rendering_server_raster.cpp b/servers/rendering/rendering_server_raster.cpp index d30160702b..b12e2ff3c1 100644 --- a/servers/rendering/rendering_server_raster.cpp +++ b/servers/rendering/rendering_server_raster.cpp @@ -222,6 +222,10 @@ bool RenderingServerRaster::has_feature(Features p_feature) const { return false; } +void RenderingServerRaster::sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { + RSG::scene_render->sdfgi_set_debug_probe_select(p_position, p_dir); +} + RID RenderingServerRaster::get_test_cube() { if (!test_cube.is_valid()) { test_cube = _make_test_cube(); diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index 8a3c55118d..706912b353 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -322,7 +322,8 @@ public: BIND2(light_set_negative, RID, bool) BIND2(light_set_cull_mask, RID, uint32_t) BIND2(light_set_reverse_cull_face_mode, RID, bool) - BIND2(light_set_use_gi, RID, bool) + BIND2(light_set_bake_mode, RID, LightBakeMode) + BIND2(light_set_max_sdfgi_cascade, RID, uint32_t) BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) @@ -336,9 +337,9 @@ public: BIND2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode) BIND2(reflection_probe_set_intensity, RID, float) - BIND2(reflection_probe_set_interior_ambient, RID, const Color &) - BIND2(reflection_probe_set_interior_ambient_energy, RID, float) - BIND2(reflection_probe_set_interior_ambient_probe_contribution, RID, float) + BIND2(reflection_probe_set_ambient_color, RID, const Color &) + BIND2(reflection_probe_set_ambient_energy, RID, float) + BIND2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode) BIND2(reflection_probe_set_max_distance, RID, float) BIND2(reflection_probe_set_extents, RID, const Vector3 &) BIND2(reflection_probe_set_origin_offset, RID, const Vector3 &) @@ -523,6 +524,7 @@ public: #define BINDBASE RSG::scene_render BIND1(directional_shadow_atlas_set_size, int) + BIND1(gi_probe_set_quality, GIProbeQuality) /* SKY API */ @@ -564,9 +566,13 @@ public: BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) BIND5(environment_set_fog_height, RID, bool, float, float, float) + BIND11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float) + BIND1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount) + BIND1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge) + BIND3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &) - BIND2(screen_space_roughness_limiter_set_active, bool, float) + BIND3(screen_space_roughness_limiter_set_active, bool, float, float) BIND1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality) BIND2(sub_surface_scattering_set_scale, float, float) @@ -793,6 +799,8 @@ public: virtual bool is_low_end() const; + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir); + RenderingServerRaster(); ~RenderingServerRaster(); diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp index 7b8504036e..75a5834791 100644 --- a/servers/rendering/rendering_server_scene.cpp +++ b/servers/rendering/rendering_server_scene.cpp @@ -369,6 +369,11 @@ void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) { switch (instance->base_type) { case RS::INSTANCE_LIGHT: { InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data); + + if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + instance->scenario->dynamic_lights.erase(light->instance); + } + #ifdef DEBUG_ENABLED if (light->geometries.size()) { ERR_PRINT("BUG, indexing did not unpair geometries from light."); @@ -976,7 +981,26 @@ void RenderingServerScene::_update_instance(Instance *p_instance) { InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data); RSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform); + RSG::scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb)); light->shadow_dirty = true; + + RS::LightBakeMode bake_mode = RSG::storage->light_get_bake_mode(p_instance->base); + if (RSG::storage->light_get_type(p_instance->base) != RS::LIGHT_DIRECTIONAL && bake_mode != light->bake_mode) { + if (light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + p_instance->scenario->dynamic_lights.erase(light->instance); + } + + light->bake_mode = bake_mode; + + if (light->bake_mode == RS::LIGHT_BAKE_DYNAMIC) { + p_instance->scenario->dynamic_lights.push_back(light->instance); + } + } + + uint32_t max_sdfgi_cascade = RSG::storage->light_get_max_sdfgi_cascade(p_instance->base); + if (light->max_sdfgi_cascade != max_sdfgi_cascade) { + light->max_sdfgi_cascade = max_sdfgi_cascade; //should most likely make sdfgi dirty in scenario + } } if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) { @@ -1788,8 +1812,10 @@ void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID } break; } - _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); + RID environment = _render_get_environment(p_camera, p_scenario); + + _prepare_scene(camera->transform, camera_matrix, ortho, camera->vaspect, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); #endif } @@ -1808,6 +1834,8 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface> Transform world_origin = XRServer::get_singleton()->get_world_origin(); Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin); + RID environment = _render_get_environment(p_camera, p_scenario); + // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye if (p_eye == XRInterface::EYE_LEFT) { // Center our transform, we assume basis is equal. @@ -1865,17 +1893,17 @@ void RenderingServerScene::render_camera(RID p_render_buffers, Ref<XRInterface> mono_transform *= apply_z_shift; // now prepare our scene with our adjusted transform projection matrix - _prepare_scene(mono_transform, combined_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + _prepare_scene(mono_transform, combined_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); } else if (p_eye == XRInterface::EYE_MONO) { // For mono render, prepare as per usual - _prepare_scene(cam_transform, camera_matrix, false, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + _prepare_scene(cam_transform, camera_matrix, false, false, p_render_buffers, environment, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); } // And render our scene... - _render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); + _render_scene(p_render_buffers, cam_transform, camera_matrix, false, environment, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); }; -void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) { +void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) { // Note, in stereo rendering: // - p_cam_transform will be a transform in the middle of our two eyes // - p_cam_projection is a wider frustrum that encompasses both eyes @@ -1887,6 +1915,10 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const RSG::scene_render->set_scene_pass(render_pass); + if (p_render_buffers.is_valid()) { + RSG::scene_render->sdfgi_update(p_render_buffers, p_environment, p_cam_transform.origin); //update conditions for SDFGI (whether its used or not) + } + RENDER_TIMESTAMP("Frustum Culling"); //rasterizer->set_camera(camera->transform, camera_matrix,ortho); @@ -2224,22 +2256,97 @@ void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const } } } + + /* UPDATE SDFGI */ + + if (p_render_buffers.is_valid()) { + uint32_t cascade_index[8]; + uint32_t cascade_sizes[8]; + const RID *cascade_ptrs[8]; + uint32_t cascade_count = 0; + uint32_t sdfgi_light_cull_count = 0; + + uint32_t prev_cascade = 0xFFFFFFFF; + for (int i = 0; i < RSG::scene_render->sdfgi_get_pending_region_count(p_render_buffers); i++) { + AABB region = RSG::scene_render->sdfgi_get_pending_region_bounds(p_render_buffers, i); + uint32_t region_cascade = RSG::scene_render->sdfgi_get_pending_region_cascade(p_render_buffers, i); + + if (region_cascade != prev_cascade) { + cascade_sizes[cascade_count] = 0; + cascade_index[cascade_count] = region_cascade; + cascade_ptrs[cascade_count] = &sdfgi_light_cull_result[sdfgi_light_cull_count]; + cascade_count++; + sdfgi_light_cull_pass++; + prev_cascade = region_cascade; + } + uint32_t sdfgi_cull_count = scenario->octree.cull_aabb(region, instance_shadow_cull_result, MAX_INSTANCE_CULL); + + for (uint32_t j = 0; j < sdfgi_cull_count; j++) { + Instance *ins = instance_shadow_cull_result[j]; + + bool keep = false; + + if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) { + InstanceLightData *instance_light = (InstanceLightData *)ins->base_data; + if (instance_light->bake_mode != RS::LIGHT_BAKE_STATIC || region_cascade > instance_light->max_sdfgi_cascade) { + continue; + } + + if (sdfgi_light_cull_pass != instance_light->sdfgi_cascade_light_pass && sdfgi_light_cull_count < MAX_LIGHTS_CULLED) { + instance_light->sdfgi_cascade_light_pass = sdfgi_light_cull_pass; + sdfgi_light_cull_result[sdfgi_light_cull_count++] = instance_light->instance; + cascade_sizes[cascade_count - 1]++; + } + } else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + if (ins->baked_light) { + keep = true; + } + } + + if (!keep) { + // remove, no reason to keep + sdfgi_cull_count--; + SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[sdfgi_cull_count]); + j--; + } + } + + RSG::scene_render->render_sdfgi(p_render_buffers, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count); + //have to save updated cascades, then update static lights. + } + + if (sdfgi_light_cull_count) { + RSG::scene_render->render_sdfgi_static_lights(p_render_buffers, cascade_count, cascade_index, cascade_ptrs, cascade_sizes); + } + + RSG::scene_render->sdfgi_update_probes(p_render_buffers, p_environment, directional_light_ptr, directional_light_count, scenario->dynamic_lights.ptr(), scenario->dynamic_lights.size()); + } } -void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { - Scenario *scenario = scenario_owner.getornull(p_scenario); +RID RenderingServerScene::_render_get_environment(RID p_camera, RID p_scenario) { + Camera *camera = camera_owner.getornull(p_camera); + if (camera && RSG::scene_render->is_environment(camera->env)) { + return camera->env; + } - /* ENVIRONMENT */ + Scenario *scenario = scenario_owner.getornull(p_scenario); + if (!scenario) { + return RID(); + } + if (RSG::scene_render->is_environment(scenario->environment)) { + return scenario->environment; + } - RID environment; - if (p_force_environment.is_valid()) { //camera has more environment priority - environment = p_force_environment; - } else if (scenario->environment.is_valid()) { - environment = scenario->environment; - } else { - environment = scenario->fallback_environment; + if (RSG::scene_render->is_environment(scenario->fallback_environment)) { + return scenario->fallback_environment; } + return RID(); +} + +void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { + Scenario *scenario = scenario_owner.getornull(p_scenario); + RID camera_effects; if (p_force_camera_effects.is_valid()) { camera_effects = p_force_camera_effects; @@ -2249,7 +2356,7 @@ void RenderingServerScene::_render_scene(RID p_render_buffers, const Transform p /* PROCESS GEOMETRY AND DRAW SCENE */ RENDER_TIMESTAMP("Render Scene "); - RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); + RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, decal_instance_cull_result, decal_cull_count, (RasterizerScene::InstanceBase **)lightmap_cull_result, lightmap_cull_count, p_environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); } void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h index f2e2918f21..165c3784c1 100644 --- a/servers/rendering/rendering_server_scene.h +++ b/servers/rendering/rendering_server_scene.h @@ -33,6 +33,8 @@ #include "servers/rendering/rasterizer.h" +#include "core/local_vector.h" +#include "core/math/geometry_3d.h" #include "core/math/octree.h" #include "core/os/semaphore.h" #include "core/os/thread.h" @@ -121,6 +123,8 @@ public: SelfList<Instance>::List instances; + LocalVector<RID> dynamic_lights; + Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; } }; @@ -309,7 +313,13 @@ public: Instance *baked_light; + RS::LightBakeMode bake_mode; + uint32_t max_sdfgi_cascade = 2; + + uint64_t sdfgi_cascade_light_pass = 0; + InstanceLightData() { + bake_mode = RS::LIGHT_BAKE_DISABLED; shadow_dirty = true; D = nullptr; last_version = 0; @@ -379,7 +389,9 @@ public: Instance *instance_cull_result[MAX_INSTANCE_CULL]; Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps Instance *light_cull_result[MAX_LIGHTS_CULLED]; + RID sdfgi_light_cull_result[MAX_LIGHTS_CULLED]; RID light_instance_cull_result[MAX_LIGHTS_CULLED]; + uint64_t sdfgi_light_cull_pass = 0; int light_cull_count; int directional_light_count; RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED]; @@ -438,9 +450,11 @@ public: _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario); + RID _render_get_environment(RID p_camera, RID p_scenario); + bool _render_reflection_probe_step(Instance *p_instance, int p_step); - void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true); - void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_render_buffers, RID p_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true); + void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas); void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index a746aa52b2..60a694eed5 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -237,7 +237,8 @@ public: FUNC2(light_set_negative, RID, bool) FUNC2(light_set_cull_mask, RID, uint32_t) FUNC2(light_set_reverse_cull_face_mode, RID, bool) - FUNC2(light_set_use_gi, RID, bool) + FUNC2(light_set_bake_mode, RID, LightBakeMode) + FUNC2(light_set_max_sdfgi_cascade, RID, uint32_t) FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) @@ -251,9 +252,9 @@ public: FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode) FUNC2(reflection_probe_set_intensity, RID, float) - FUNC2(reflection_probe_set_interior_ambient, RID, const Color &) - FUNC2(reflection_probe_set_interior_ambient_energy, RID, float) - FUNC2(reflection_probe_set_interior_ambient_probe_contribution, RID, float) + FUNC2(reflection_probe_set_ambient_color, RID, const Color &) + FUNC2(reflection_probe_set_ambient_energy, RID, float) + FUNC2(reflection_probe_set_ambient_mode, RID, ReflectionProbeAmbientMode) FUNC2(reflection_probe_set_max_distance, RID, float) FUNC2(reflection_probe_set_extents, RID, const Vector3 &) FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &) @@ -321,6 +322,8 @@ public: FUNC2(gi_probe_set_anisotropy_strength, RID, float) FUNC1RC(float, gi_probe_get_anisotropy_strength, RID) + FUNC1(gi_probe_set_quality, GIProbeQuality) + /* LIGHTMAP CAPTURE */ FUNCRID(lightmap) @@ -465,6 +468,10 @@ public: FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) + FUNC11(environment_set_sdfgi, RID, bool, EnvironmentSDFGICascades, float, EnvironmentSDFGIYScale, bool, bool, bool, float, float, float) + FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount) + FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge) + FUNC11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) FUNC1(environment_glow_set_use_bicubic_upscale, bool) @@ -478,7 +485,7 @@ public: FUNC3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &) - FUNC2(screen_space_roughness_limiter_set_active, bool, float) + FUNC3(screen_space_roughness_limiter_set_active, bool, float, float) FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality) FUNC2(sub_surface_scattering_set_scale, float, float) @@ -714,6 +721,10 @@ public: return rendering_server->get_frame_profile(); } + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) { + rendering_server->sdfgi_set_debug_probe_select(p_position, p_dir); + } + RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread); ~RenderingServerWrapMT(); diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 14a28554f9..99cc76b2e3 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -643,7 +643,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() { } if (hexa_found) { - tk.constant = (double)str.hex_to_int64(true); + tk.constant = (double)str.hex_to_int(true); } else { tk.constant = str.to_double(); } @@ -982,6 +982,9 @@ bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_rea if (r_struct_name) { *r_struct_name = function->arguments[i].type_str; } + if (r_is_const) { + *r_is_const = function->arguments[i].is_const; + } return true; } } @@ -3553,7 +3556,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons for (int i = 0; i < call_function->arguments.size(); i++) { int argidx = i + 1; if (argidx < func->arguments.size()) { - if (call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) { + if (call_function->arguments[i].is_const || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) { bool error = false; Node *n = func->arguments[argidx]; if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) { @@ -5585,6 +5588,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } else if (tk.type == TK_CF_RETURN) { //check return type BlockNode *b = p_block; + + if (b && b->parent_function && (b->parent_function->name == "vertex" || b->parent_function->name == "fragment" || b->parent_function->name == "light")) { + _set_error(vformat("Using 'return' in '%s' processor function results in undefined behavior!", b->parent_function->name)); + return ERR_PARSE_ERROR; + } + while (b && !b->parent_function) { b = b->parent_block; } @@ -6774,15 +6783,29 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct break; } + bool is_const = false; + if (tk.type == TK_CONST) { + is_const = true; + tk = _get_token(); + } + ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN; if (tk.type == TK_ARG_IN) { qualifier = ARGUMENT_QUALIFIER_IN; tk = _get_token(); } else if (tk.type == TK_ARG_OUT) { + if (is_const) { + _set_error("'out' qualifier cannot be used within a function parameter declared with 'const'."); + return ERR_PARSE_ERROR; + } qualifier = ARGUMENT_QUALIFIER_OUT; tk = _get_token(); } else if (tk.type == TK_ARG_INOUT) { + if (is_const) { + _set_error("'inout' qualifier cannot be used within a function parameter declared with 'const'."); + return ERR_PARSE_ERROR; + } qualifier = ARGUMENT_QUALIFIER_INOUT; tk = _get_token(); } @@ -6871,6 +6894,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct arg.tex_builtin_check = false; arg.tex_argument_filter = FILTER_DEFAULT; arg.tex_argument_repeat = REPEAT_DEFAULT; + arg.is_const = is_const; func_node->arguments.push_back(arg); @@ -7267,6 +7291,10 @@ Error ShaderLanguage::complete(const String &p_code, const Map<StringName, Funct calltip += CharType(0xFFFF); } + if (shader->functions[i].function->arguments[j].is_const) { + calltip += "const "; + } + if (shader->functions[i].function->arguments[j].qualifier != ArgumentQualifier::ARGUMENT_QUALIFIER_IN) { if (shader->functions[i].function->arguments[j].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT) { calltip += "out "; diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index bc8f03774a..faf06a9a85 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -554,6 +554,7 @@ public: TextureRepeat tex_argument_repeat; bool tex_builtin_check; StringName tex_builtin; + bool is_const; Map<StringName, Set<int>> tex_argument_connect; }; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 2601efa9e2..06cb6171a5 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -114,6 +114,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL_ROUGHNESS_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 7edab1418d..c156313c15 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -1608,7 +1608,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &RenderingServer::light_set_negative); ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask); ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode); - ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &RenderingServer::light_set_use_gi); + ClassDB::bind_method(D_METHOD("light_set_bake_mode", "light", "bake_mode"), &RenderingServer::light_set_bake_mode); ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &RenderingServer::light_omni_set_shadow_mode); @@ -1619,9 +1619,9 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("reflection_probe_create"), &RenderingServer::reflection_probe_create); ClassDB::bind_method(D_METHOD("reflection_probe_set_update_mode", "probe", "mode"), &RenderingServer::reflection_probe_set_update_mode); ClassDB::bind_method(D_METHOD("reflection_probe_set_intensity", "probe", "intensity"), &RenderingServer::reflection_probe_set_intensity); - ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient", "probe", "color"), &RenderingServer::reflection_probe_set_interior_ambient); - ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_energy", "probe", "energy"), &RenderingServer::reflection_probe_set_interior_ambient_energy); - ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_probe_contribution", "probe", "contrib"), &RenderingServer::reflection_probe_set_interior_ambient_probe_contribution); + ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_mode", "probe", "mode"), &RenderingServer::reflection_probe_set_ambient_mode); + ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_color", "probe", "color"), &RenderingServer::reflection_probe_set_ambient_color); + ClassDB::bind_method(D_METHOD("reflection_probe_set_ambient_energy", "probe", "energy"), &RenderingServer::reflection_probe_set_ambient_energy); ClassDB::bind_method(D_METHOD("reflection_probe_set_max_distance", "probe", "distance"), &RenderingServer::reflection_probe_set_max_distance); ClassDB::bind_method(D_METHOD("reflection_probe_set_extents", "probe", "extents"), &RenderingServer::reflection_probe_set_extents); ClassDB::bind_method(D_METHOD("reflection_probe_set_origin_offset", "probe", "offset"), &RenderingServer::reflection_probe_set_origin_offset); @@ -1995,6 +1995,10 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS); BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX); + BIND_ENUM_CONSTANT(LIGHT_BAKE_DISABLED); + BIND_ENUM_CONSTANT(LIGHT_BAKE_DYNAMIC); + BIND_ENUM_CONSTANT(LIGHT_BAKE_STATIC); + BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID); BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE); @@ -2008,6 +2012,10 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE); BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS); + BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_DISABLED); + BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_ENVIRONMENT); + BIND_ENUM_CONSTANT(REFLECTION_PROBE_AMBIENT_COLOR); + BIND_ENUM_CONSTANT(DECAL_TEXTURE_ALBEDO); BIND_ENUM_CONSTANT(DECAL_TEXTURE_NORMAL); BIND_ENUM_CONSTANT(DECAL_TEXTURE_ORM); @@ -2060,9 +2068,11 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSAO); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_PSSM_SPLITS); BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DECAL_ATLAS); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SDFGI); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SDFGI_PROBES); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_BUFFER); BIND_ENUM_CONSTANT(SKY_MODE_QUALITY); BIND_ENUM_CONSTANT(SKY_MODE_REALTIME); @@ -2346,7 +2356,7 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false); GLOBAL_DEF("rendering/quality/gi_probes/quality", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Lowest (1 Cone - Fast),Medium (4 Cones - Average),High (6 Cones - Slow)")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Low (4 Cones - Fast),High (6 Cones - Slow)")); GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false); GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true); @@ -2372,10 +2382,11 @@ RenderingServer::RenderingServer() { ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/quality", PropertyInfo(Variant::INT, "rendering/quality/ssao/quality", PROPERTY_HINT_ENUM, "Low (Fast),Medium (Average),High (Slow),Ultra (Slower)")); GLOBAL_DEF("rendering/quality/ssao/half_size", false); - GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter", PropertyInfo(Variant::INT, "rendering/quality/screen_filters/screen_space_roughness_limiter", PROPERTY_HINT_ENUM, "Disabled (Fast),Enabled (Average)")); - GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_curve", 1.0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_curve", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_curve", PROPERTY_HINT_EXP_EASING, "0.01,8,0.01")); + GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_enabled", true); + GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_amount", 0.25); + GLOBAL_DEF("rendering/quality/screen_filters/screen_space_roughness_limiter_limit", 0.18); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_amount", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/screen_filters/screen_space_roughness_limiter_limit", PropertyInfo(Variant::FLOAT, "rendering/quality/screen_filters/screen_space_roughness_limiter_limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01")); GLOBAL_DEF("rendering/quality/glow/upscale_mode", 1); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/glow/upscale_mode", PropertyInfo(Variant::INT, "rendering/quality/glow/upscale_mode", PROPERTY_HINT_ENUM, "Linear (Fast),Bicubic (Slow)")); @@ -2395,6 +2406,11 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/lightmapper/probe_capture_update_speed", 15); ProjectSettings::get_singleton()->set_custom_property_info("rendering/lightmapper/probe_capture_update_speed", PropertyInfo(Variant::FLOAT, "rendering/lightmapper/probe_capture_update_speed", PROPERTY_HINT_RANGE, "0.001,256,0.001")); + + GLOBAL_DEF("rendering/sdfgi/probe_ray_count", 2); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/sdfgi/probe_ray_count", PropertyInfo(Variant::INT, "rendering/sdfgi/probe_ray_count", PROPERTY_HINT_ENUM, "8 (Fastest),16,32,64,96,128 (Slowest)")); + GLOBAL_DEF("rendering/sdfgi/frames_to_converge", 1); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/sdfgi/frames_to_converge", PropertyInfo(Variant::INT, "rendering/sdfgi/frames_to_converge", PROPERTY_HINT_ENUM, "5 (Less Latency but Lower Quality),10,15,20,25,30 (More Latency but Higher Quality)")); } RenderingServer::~RenderingServer() { diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 56a8325630..2e5ceec02f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -406,7 +406,15 @@ public: virtual void light_set_negative(RID p_light, bool p_enable) = 0; virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; - virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; + + enum LightBakeMode { + LIGHT_BAKE_DISABLED, + LIGHT_BAKE_DYNAMIC, + LIGHT_BAKE_STATIC, + }; + + virtual void light_set_bake_mode(RID p_light, LightBakeMode p_bake_mode) = 0; + virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) = 0; // omni light enum LightOmniShadowMode { @@ -420,7 +428,7 @@ public: enum LightDirectionalShadowMode { LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, - LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS + LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS, }; virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0; @@ -429,7 +437,6 @@ public: enum LightDirectionalShadowDepthRangeMode { LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, - }; virtual void light_directional_set_shadow_depth_range_mode(RID p_light, LightDirectionalShadowDepthRangeMode p_range_mode) = 0; @@ -445,9 +452,16 @@ public: virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode) = 0; virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; - virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_color) = 0; - virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0; - virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0; + + enum ReflectionProbeAmbientMode { + REFLECTION_PROBE_AMBIENT_DISABLED, + REFLECTION_PROBE_AMBIENT_ENVIRONMENT, + REFLECTION_PROBE_AMBIENT_COLOR, + }; + + virtual void reflection_probe_set_ambient_mode(RID p_probe, ReflectionProbeAmbientMode p_mode) = 0; + virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) = 0; + virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) = 0; virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; @@ -522,6 +536,13 @@ public: virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; + enum GIProbeQuality { + GI_PROBE_QUALITY_LOW, + GI_PROBE_QUALITY_HIGH, + }; + + virtual void gi_probe_set_quality(GIProbeQuality) = 0; + /* LIGHTMAP */ virtual RID lightmap_create() = 0; @@ -586,16 +607,6 @@ public: virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0; virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0; - /* - enum ParticlesCollisionMode { - PARTICLES_COLLISION_NONE, - PARTICLES_COLLISION_TEXTURE, - PARTICLES_COLLISION_CUBEMAP, - }; - - virtual void particles_set_collision(RID p_particles,ParticlesCollisionMode p_mode,const Transform&, p_xform,const RID p_depth_tex,const RID p_normal_tex)=0; - */ - /* VIEWPORT TARGET API */ virtual RID viewport_create() = 0; @@ -690,9 +701,12 @@ public: VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE, VIEWPORT_DEBUG_DRAW_SSAO, - VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER, VIEWPORT_DEBUG_DRAW_PSSM_SPLITS, VIEWPORT_DEBUG_DRAW_DECAL_ATLAS, + VIEWPORT_DEBUG_DRAW_SDFGI, + VIEWPORT_DEBUG_DRAW_SDFGI_PROBES, + VIEWPORT_DEBUG_DRAW_GI_BUFFER, + }; virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0; @@ -807,13 +821,51 @@ public: virtual void environment_set_ssao_quality(EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; + enum EnvironmentSDFGICascades { + ENV_SDFGI_CASCADES_4, + ENV_SDFGI_CASCADES_6, + ENV_SDFGI_CASCADES_8, + }; + + enum EnvironmentSDFGIYScale { + ENV_SDFGI_Y_SCALE_DISABLED, + ENV_SDFGI_Y_SCALE_75_PERCENT, + ENV_SDFGI_Y_SCALE_50_PERCENT + }; + + virtual void environment_set_sdfgi(RID p_env, bool p_enable, EnvironmentSDFGICascades p_cascades, float p_min_cell_size, EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, bool p_use_multibounce, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0; + + enum EnvironmentSDFGIRayCount { + ENV_SDFGI_RAY_COUNT_8, + ENV_SDFGI_RAY_COUNT_16, + ENV_SDFGI_RAY_COUNT_32, + ENV_SDFGI_RAY_COUNT_64, + ENV_SDFGI_RAY_COUNT_96, + ENV_SDFGI_RAY_COUNT_128, + ENV_SDFGI_RAY_COUNT_MAX, + }; + + virtual void environment_set_sdfgi_ray_count(EnvironmentSDFGIRayCount p_ray_count) = 0; + + enum EnvironmentSDFGIFramesToConverge { + ENV_SDFGI_CONVERGE_IN_5_FRAMES, + ENV_SDFGI_CONVERGE_IN_10_FRAMES, + ENV_SDFGI_CONVERGE_IN_15_FRAMES, + ENV_SDFGI_CONVERGE_IN_20_FRAMES, + ENV_SDFGI_CONVERGE_IN_25_FRAMES, + ENV_SDFGI_CONVERGE_IN_30_FRAMES, + ENV_SDFGI_CONVERGE_MAX + }; + + virtual void environment_set_sdfgi_frames_to_converge(EnvironmentSDFGIFramesToConverge p_frames) = 0; + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; enum SubSurfaceScatteringQuality { SUB_SURFACE_SCATTERING_QUALITY_DISABLED, @@ -1207,6 +1259,8 @@ public: virtual RID get_test_texture(); virtual RID get_white_texture(); + virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0; + virtual RID make_sphere_mesh(int p_lats, int p_lons, float p_radius); virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry3D::MeshData &p_mesh_data); @@ -1248,10 +1302,12 @@ VARIANT_ENUM_CAST(RenderingServer::BlendShapeMode); VARIANT_ENUM_CAST(RenderingServer::MultimeshTransformFormat); VARIANT_ENUM_CAST(RenderingServer::LightType); VARIANT_ENUM_CAST(RenderingServer::LightParam); +VARIANT_ENUM_CAST(RenderingServer::LightBakeMode); VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode); VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode); VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowDepthRangeMode); VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode); +VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeAmbientMode); VARIANT_ENUM_CAST(RenderingServer::DecalTexture); VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder); VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode); diff --git a/thirdparty/README.md b/thirdparty/README.md index c69ca17fd0..43cd448a00 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -304,10 +304,10 @@ changes are marked with `// -- GODOT --` comments. ## mbedtls - Upstream: https://tls.mbed.org/ -- Version: 2.16.6 (2020) +- Version: 2.16.7 (2020) - License: Apache 2.0 -File extracted from upstream release tarball (`-apache.tgz` variant): +File extracted from upstream release tarball: - All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` - All `*.c` from `library/` to `thirdparty/mbedtls/library/` @@ -623,7 +623,7 @@ Patches in the `patches` directory should be re-applied after updates. ## wslay - Upstream: https://github.com/tatsuhiro-t/wslay -- Version: 1.1.0 (2018) +- Version: 1.1.1 (2020) - License: MIT File extracted from upstream release tarball: diff --git a/thirdparty/mbedtls/LICENSE b/thirdparty/mbedtls/LICENSE index 546a8e631f..e15ea821d2 100644 --- a/thirdparty/mbedtls/LICENSE +++ b/thirdparty/mbedtls/LICENSE @@ -1,2 +1,5 @@ -Unless specifically indicated otherwise in a file, files are licensed -under the Apache 2.0 license, as can be found in: apache-2.0.txt +Unless specifically indicated otherwise in a file, Mbed TLS files are provided +under the Apache License 2.0, or the GNU General Public License v2.0 or later +(SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later). + +A copy of these licenses can be found in apache-2.0.txt and gpl-2.0.txt diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h index 94e7282d36..d20cdbd6da 100644 --- a/thirdparty/mbedtls/include/mbedtls/aes.h +++ b/thirdparty/mbedtls/include/mbedtls/aes.h @@ -20,8 +20,15 @@ * <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>. */ -/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -35,6 +42,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/aesni.h b/thirdparty/mbedtls/include/mbedtls/aesni.h index a4ca012f8a..91a4e0f116 100644 --- a/thirdparty/mbedtls/include/mbedtls/aesni.h +++ b/thirdparty/mbedtls/include/mbedtls/aesni.h @@ -8,7 +8,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -22,6 +28,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_AESNI_H diff --git a/thirdparty/mbedtls/include/mbedtls/arc4.h b/thirdparty/mbedtls/include/mbedtls/arc4.h index fb044d5b7f..ecaf310122 100644 --- a/thirdparty/mbedtls/include/mbedtls/arc4.h +++ b/thirdparty/mbedtls/include/mbedtls/arc4.h @@ -8,7 +8,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -22,6 +28,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) * */ diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h index 1e8956ed13..66f2668bf3 100644 --- a/thirdparty/mbedtls/include/mbedtls/aria.h +++ b/thirdparty/mbedtls/include/mbedtls/aria.h @@ -9,8 +9,15 @@ * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) * and also described by the IETF in <em>RFC 5794</em>. */ -/* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -24,6 +31,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/asn1.h b/thirdparty/mbedtls/include/mbedtls/asn1.h index 96c1c9a8ab..c64038cdb5 100644 --- a/thirdparty/mbedtls/include/mbedtls/asn1.h +++ b/thirdparty/mbedtls/include/mbedtls/asn1.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ASN1_H diff --git a/thirdparty/mbedtls/include/mbedtls/asn1write.h b/thirdparty/mbedtls/include/mbedtls/asn1write.h index a194243696..4fed59371c 100644 --- a/thirdparty/mbedtls/include/mbedtls/asn1write.h +++ b/thirdparty/mbedtls/include/mbedtls/asn1write.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ASN1_WRITE_H diff --git a/thirdparty/mbedtls/include/mbedtls/base64.h b/thirdparty/mbedtls/include/mbedtls/base64.h index 0d024164c5..215255e628 100644 --- a/thirdparty/mbedtls/include/mbedtls/base64.h +++ b/thirdparty/mbedtls/include/mbedtls/base64.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_BASE64_H diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h index 22b373113e..590cde58da 100644 --- a/thirdparty/mbedtls/include/mbedtls/bignum.h +++ b/thirdparty/mbedtls/include/mbedtls/bignum.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_BIGNUM_H diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h index f01573dcaf..d2a1ebdbf4 100644 --- a/thirdparty/mbedtls/include/mbedtls/blowfish.h +++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_BLOWFISH_H diff --git a/thirdparty/mbedtls/include/mbedtls/bn_mul.h b/thirdparty/mbedtls/include/mbedtls/bn_mul.h index 748975ea51..42339b7b71 100644 --- a/thirdparty/mbedtls/include/mbedtls/bn_mul.h +++ b/thirdparty/mbedtls/include/mbedtls/bn_mul.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h index 3eeb66366d..41d6f955ba 100644 --- a/thirdparty/mbedtls/include/mbedtls/camellia.h +++ b/thirdparty/mbedtls/include/mbedtls/camellia.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CAMELLIA_H diff --git a/thirdparty/mbedtls/include/mbedtls/ccm.h b/thirdparty/mbedtls/include/mbedtls/ccm.h index f03e3b580e..3647d5094f 100644 --- a/thirdparty/mbedtls/include/mbedtls/ccm.h +++ b/thirdparty/mbedtls/include/mbedtls/ccm.h @@ -29,7 +29,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -43,6 +49,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/certs.h b/thirdparty/mbedtls/include/mbedtls/certs.h index 179ebbbad2..2a645ad0d0 100644 --- a/thirdparty/mbedtls/include/mbedtls/certs.h +++ b/thirdparty/mbedtls/include/mbedtls/certs.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CERTS_H diff --git a/thirdparty/mbedtls/include/mbedtls/chacha20.h b/thirdparty/mbedtls/include/mbedtls/chacha20.h index 2ae5e6e5f4..e2950e1a01 100644 --- a/thirdparty/mbedtls/include/mbedtls/chacha20.h +++ b/thirdparty/mbedtls/include/mbedtls/chacha20.h @@ -12,8 +12,15 @@ * \author Daniel King <damaki.gh@gmail.com> */ -/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -27,6 +34,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h index 49e615d278..bee5a3ab03 100644 --- a/thirdparty/mbedtls/include/mbedtls/chachapoly.h +++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h @@ -12,8 +12,15 @@ * \author Daniel King <damaki.gh@gmail.com> */ -/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -27,6 +34,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h index 93de091c4d..8ce73ceff1 100644 --- a/thirdparty/mbedtls/include/mbedtls/check_config.h +++ b/thirdparty/mbedtls/include/mbedtls/check_config.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -140,6 +167,16 @@ #error "MBEDTLS_ECP_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_ECP_C) && !( \ + defined(MBEDTLS_ECP_ALT) || \ + defined(MBEDTLS_CTR_DRBG_C) || \ + defined(MBEDTLS_HMAC_DRBG_C) || \ + defined(MBEDTLS_SHA512_C) || \ + defined(MBEDTLS_SHA256_C) || \ + defined(MBEDTLS_ECP_NO_INTERNAL_RNG)) +#error "MBEDTLS_ECP_C requires a DRBG or SHA-2 module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used" +#endif + #if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) #error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" #endif diff --git a/thirdparty/mbedtls/include/mbedtls/cipher.h b/thirdparty/mbedtls/include/mbedtls/cipher.h index 082a691741..8672dd2b98 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h index c6def0bef7..558be52a7e 100644 --- a/thirdparty/mbedtls/include/mbedtls/cipher_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/cipher_internal.h @@ -7,7 +7,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -21,6 +27,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_CIPHER_WRAP_H diff --git a/thirdparty/mbedtls/include/mbedtls/cmac.h b/thirdparty/mbedtls/include/mbedtls/cmac.h index 9d42b3f209..2074747567 100644 --- a/thirdparty/mbedtls/include/mbedtls/cmac.h +++ b/thirdparty/mbedtls/include/mbedtls/cmac.h @@ -8,7 +8,13 @@ */ /* * Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -22,6 +28,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h index a58b47243d..71cc4f4d97 100644 --- a/thirdparty/mbedtls/include/mbedtls/compat-1.3.h +++ b/thirdparty/mbedtls/include/mbedtls/compat-1.3.h @@ -8,7 +8,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -22,6 +28,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index 8d9c31a504..28b405ebca 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -781,6 +808,28 @@ #define MBEDTLS_ECP_NIST_OPTIM /** + * \def MBEDTLS_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very + * constrained applications that don't require this protection (for example, + * because you're only doing signature verification, so not manipulating any + * secret, or because local/physical side-channel attacks are outside your + * threat model), it might be desirable to get rid of that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** * \def MBEDTLS_ECP_RESTARTABLE * * Enable "non-blocking" ECC operations that can return early and be resumed. diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index e0b5ed9c93..894fa17130 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -39,7 +39,13 @@ */ /* * Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -53,6 +59,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/debug.h b/thirdparty/mbedtls/include/mbedtls/debug.h index 736444bb76..11928e9818 100644 --- a/thirdparty/mbedtls/include/mbedtls/debug.h +++ b/thirdparty/mbedtls/include/mbedtls/debug.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_DEBUG_H diff --git a/thirdparty/mbedtls/include/mbedtls/des.h b/thirdparty/mbedtls/include/mbedtls/des.h index 54e6b7894b..4c6441d7d9 100644 --- a/thirdparty/mbedtls/include/mbedtls/des.h +++ b/thirdparty/mbedtls/include/mbedtls/des.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) * */ diff --git a/thirdparty/mbedtls/include/mbedtls/dhm.h b/thirdparty/mbedtls/include/mbedtls/dhm.h index 2909f5fbc8..5c04ed19fb 100644 --- a/thirdparty/mbedtls/include/mbedtls/dhm.h +++ b/thirdparty/mbedtls/include/mbedtls/dhm.h @@ -45,7 +45,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -59,6 +65,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/ecdh.h b/thirdparty/mbedtls/include/mbedtls/ecdh.h index 4479a1d46f..a0052df471 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdh.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdh.h @@ -14,7 +14,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -28,6 +34,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/ecdsa.h b/thirdparty/mbedtls/include/mbedtls/ecdsa.h index 932acc6d14..bc219dcad7 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecdsa.h +++ b/thirdparty/mbedtls/include/mbedtls/ecdsa.h @@ -12,7 +12,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -26,6 +32,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h index 3d8d02ae64..1b6c6ac244 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h +++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ECJPAKE_H diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h index 065a4cc0b9..8db206060b 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp.h @@ -16,7 +16,13 @@ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -30,6 +36,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ @@ -813,6 +840,9 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, * intermediate results to prevent potential timing attacks * targeting these results. We recommend always providing * a non-NULL \p f_rng. The overhead is negligible. + * Note: unless #MBEDTLS_ECP_NO_INTERNAL_RNG is defined, when + * \p f_rng is NULL, an internal RNG (seeded from the value + * of \p m) will be used instead. * * \param grp The ECP group to use. * This must be initialized and have group parameters diff --git a/thirdparty/mbedtls/include/mbedtls/ecp_internal.h b/thirdparty/mbedtls/include/mbedtls/ecp_internal.h index 7625ed48e1..4e9445ae44 100644 --- a/thirdparty/mbedtls/include/mbedtls/ecp_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ecp_internal.h @@ -6,7 +6,13 @@ */ /* * Copyright (C) 2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h index ca06dc3c58..fd70cd7e9e 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ENTROPY_H diff --git a/thirdparty/mbedtls/include/mbedtls/entropy_poll.h b/thirdparty/mbedtls/include/mbedtls/entropy_poll.h index 94dd657eb9..9843a9e460 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy_poll.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy_poll.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ENTROPY_POLL_H diff --git a/thirdparty/mbedtls/include/mbedtls/error.h b/thirdparty/mbedtls/include/mbedtls/error.h index bee0fe485a..3ee7bbba89 100644 --- a/thirdparty/mbedtls/include/mbedtls/error.h +++ b/thirdparty/mbedtls/include/mbedtls/error.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_ERROR_H @@ -100,6 +127,7 @@ * ECP 4 10 (Started from top) * MD 5 5 * HKDF 5 1 (Started from top) + * SSL 5 1 (Started from 0x5E80) * CIPHER 6 8 * SSL 6 23 (Started from top) * SSL 7 32 diff --git a/thirdparty/mbedtls/include/mbedtls/gcm.h b/thirdparty/mbedtls/include/mbedtls/gcm.h index fd130abd7c..52d03b0ce8 100644 --- a/thirdparty/mbedtls/include/mbedtls/gcm.h +++ b/thirdparty/mbedtls/include/mbedtls/gcm.h @@ -13,7 +13,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -27,6 +33,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/havege.h b/thirdparty/mbedtls/include/mbedtls/havege.h index 4c1c86087a..75ab3cb963 100644 --- a/thirdparty/mbedtls/include/mbedtls/havege.h +++ b/thirdparty/mbedtls/include/mbedtls/havege.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_HAVEGE_H diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h index bcafe42513..a8db554d9f 100644 --- a/thirdparty/mbedtls/include/mbedtls/hkdf.h +++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h @@ -8,7 +8,13 @@ */ /* * Copyright (C) 2016-2019, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -22,6 +28,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_HKDF_H diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index 7931c2281c..231fb459bc 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2019, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_HMAC_DRBG_H diff --git a/thirdparty/mbedtls/include/mbedtls/md.h b/thirdparty/mbedtls/include/mbedtls/md.h index 8bcf766a6c..6a21f05908 100644 --- a/thirdparty/mbedtls/include/mbedtls/md.h +++ b/thirdparty/mbedtls/include/mbedtls/md.h @@ -7,7 +7,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -21,6 +27,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ @@ -98,6 +125,8 @@ typedef struct mbedtls_md_context_t * \brief This function returns the list of digests supported by the * generic digest module. * + * \note The list starts with the strongest available hashes. + * * \return A statically allocated array of digests. Each element * in the returned list is an integer belonging to the * message-digest enumeration #mbedtls_md_type_t. diff --git a/thirdparty/mbedtls/include/mbedtls/md2.h b/thirdparty/mbedtls/include/mbedtls/md2.h index fe97cf08d4..6d563b41be 100644 --- a/thirdparty/mbedtls/include/mbedtls/md2.h +++ b/thirdparty/mbedtls/include/mbedtls/md2.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) * */ diff --git a/thirdparty/mbedtls/include/mbedtls/md4.h b/thirdparty/mbedtls/include/mbedtls/md4.h index ce703c0ba4..3f4bcdc607 100644 --- a/thirdparty/mbedtls/include/mbedtls/md4.h +++ b/thirdparty/mbedtls/include/mbedtls/md4.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) * */ diff --git a/thirdparty/mbedtls/include/mbedtls/md5.h b/thirdparty/mbedtls/include/mbedtls/md5.h index 6eed6cc864..34279c7212 100644 --- a/thirdparty/mbedtls/include/mbedtls/md5.h +++ b/thirdparty/mbedtls/include/mbedtls/md5.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_MD5_H diff --git a/thirdparty/mbedtls/include/mbedtls/md_internal.h b/thirdparty/mbedtls/include/mbedtls/md_internal.h index 04de482918..154b8bbc27 100644 --- a/thirdparty/mbedtls/include/mbedtls/md_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/md_internal.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_MD_WRAP_H diff --git a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h index 705f9a6369..c1e0926b13 100644 --- a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h +++ b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H diff --git a/thirdparty/mbedtls/include/mbedtls/net.h b/thirdparty/mbedtls/include/mbedtls/net.h index 8cead58e5d..bba4a35940 100644 --- a/thirdparty/mbedtls/include/mbedtls/net.h +++ b/thirdparty/mbedtls/include/mbedtls/net.h @@ -7,7 +7,13 @@ */ /* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -21,6 +27,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index 4c7ef00fe6..d4d23fe9d8 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -21,7 +21,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -35,6 +41,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_NET_SOCKETS_H diff --git a/thirdparty/mbedtls/include/mbedtls/nist_kw.h b/thirdparty/mbedtls/include/mbedtls/nist_kw.h index 3b67b59cd2..f2b9cebf9c 100644 --- a/thirdparty/mbedtls/include/mbedtls/nist_kw.h +++ b/thirdparty/mbedtls/include/mbedtls/nist_kw.h @@ -17,7 +17,13 @@ */ /* * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -31,6 +37,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h index 6fbd018aaa..7fe4b38621 100644 --- a/thirdparty/mbedtls/include/mbedtls/oid.h +++ b/thirdparty/mbedtls/include/mbedtls/oid.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_OID_H diff --git a/thirdparty/mbedtls/include/mbedtls/padlock.h b/thirdparty/mbedtls/include/mbedtls/padlock.h index 721a5d4930..bd476f5f38 100644 --- a/thirdparty/mbedtls/include/mbedtls/padlock.h +++ b/thirdparty/mbedtls/include/mbedtls/padlock.h @@ -9,7 +9,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -23,6 +29,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PADLOCK_H diff --git a/thirdparty/mbedtls/include/mbedtls/pem.h b/thirdparty/mbedtls/include/mbedtls/pem.h index a29e9ce300..16b6101415 100644 --- a/thirdparty/mbedtls/include/mbedtls/pem.h +++ b/thirdparty/mbedtls/include/mbedtls/pem.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PEM_H diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h index 136427503a..408f7baee7 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk.h +++ b/thirdparty/mbedtls/include/mbedtls/pk.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/pk_internal.h b/thirdparty/mbedtls/include/mbedtls/pk_internal.h index 48b7a5f7bf..1cd05943ba 100644 --- a/thirdparty/mbedtls/include/mbedtls/pk_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/pk_internal.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs11.h b/thirdparty/mbedtls/include/mbedtls/pkcs11.h index 02427ddc1e..e1446120c8 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs11.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs11.h @@ -7,7 +7,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -21,6 +27,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PKCS11_H diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs12.h b/thirdparty/mbedtls/include/mbedtls/pkcs12.h index d441357b7f..c418e8f243 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs12.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs12.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PKCS12_H diff --git a/thirdparty/mbedtls/include/mbedtls/pkcs5.h b/thirdparty/mbedtls/include/mbedtls/pkcs5.h index c92185f7a6..c3f645aff1 100644 --- a/thirdparty/mbedtls/include/mbedtls/pkcs5.h +++ b/thirdparty/mbedtls/include/mbedtls/pkcs5.h @@ -7,7 +7,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -21,6 +27,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PKCS5_H diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h index 89fe8a7b19..dcb5a88eeb 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform.h +++ b/thirdparty/mbedtls/include/mbedtls/platform.h @@ -14,7 +14,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -28,6 +34,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PLATFORM_H diff --git a/thirdparty/mbedtls/include/mbedtls/platform_time.h b/thirdparty/mbedtls/include/mbedtls/platform_time.h index 2ed36f56c9..a45870c3a6 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform_time.h +++ b/thirdparty/mbedtls/include/mbedtls/platform_time.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PLATFORM_TIME_H diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h index 09d0965182..f10574afe6 100644 --- a/thirdparty/mbedtls/include/mbedtls/platform_util.h +++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h @@ -6,7 +6,13 @@ */ /* * Copyright (C) 2018, Arm Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_PLATFORM_UTIL_H diff --git a/thirdparty/mbedtls/include/mbedtls/poly1305.h b/thirdparty/mbedtls/include/mbedtls/poly1305.h index f0ec44c968..6e45b2c2ba 100644 --- a/thirdparty/mbedtls/include/mbedtls/poly1305.h +++ b/thirdparty/mbedtls/include/mbedtls/poly1305.h @@ -12,8 +12,15 @@ * \author Daniel King <damaki.gh@gmail.com> */ -/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -27,6 +34,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/include/mbedtls/ripemd160.h b/thirdparty/mbedtls/include/mbedtls/ripemd160.h index b42f6d2a95..505c39252e 100644 --- a/thirdparty/mbedtls/include/mbedtls/ripemd160.h +++ b/thirdparty/mbedtls/include/mbedtls/ripemd160.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_RIPEMD160_H diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h index 35bacd8763..cd22fc4c1f 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa.h @@ -11,7 +11,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -25,6 +31,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_RSA_H diff --git a/thirdparty/mbedtls/include/mbedtls/rsa_internal.h b/thirdparty/mbedtls/include/mbedtls/rsa_internal.h index 53abd3c5b0..2464e6b082 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa_internal.h @@ -36,7 +36,13 @@ */ /* * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -50,6 +56,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) * */ diff --git a/thirdparty/mbedtls/include/mbedtls/sha1.h b/thirdparty/mbedtls/include/mbedtls/sha1.h index bb6ecf05a4..e69db8a15a 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha1.h +++ b/thirdparty/mbedtls/include/mbedtls/sha1.h @@ -12,7 +12,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -26,6 +32,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA1_H diff --git a/thirdparty/mbedtls/include/mbedtls/sha256.h b/thirdparty/mbedtls/include/mbedtls/sha256.h index d64739820c..5b03bc31dc 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha256.h +++ b/thirdparty/mbedtls/include/mbedtls/sha256.h @@ -8,7 +8,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -22,6 +28,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA256_H diff --git a/thirdparty/mbedtls/include/mbedtls/sha512.h b/thirdparty/mbedtls/include/mbedtls/sha512.h index c06ceed1d1..2fbc69f80e 100644 --- a/thirdparty/mbedtls/include/mbedtls/sha512.h +++ b/thirdparty/mbedtls/include/mbedtls/sha512.h @@ -7,7 +7,13 @@ */ /* * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -21,6 +27,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SHA512_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h index 1adf9608cc..6f56983562 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_H @@ -123,6 +150,7 @@ #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ #define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */ #define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */ +#define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 /**< Invalid value in SSL config */ /* * Various constants @@ -137,6 +165,9 @@ #define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ #define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ +#define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ + +#define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c * NONE must be zero so that memset()ing structure to zero works */ diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h index 52ba0948c5..e987c29e11 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_CACHE_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h index 71053e5ba7..8969141165 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_CIPHERSUITES_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h index e34760ae85..71e056781c 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_COOKIE_H diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h index bd5ad94dbf..b371094f1e 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_INTERNAL_H @@ -182,6 +209,12 @@ : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ ) +/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */ +#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN 65534 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + /* * Check that we obey the standard's message size bounds */ @@ -236,6 +269,41 @@ #define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) +/** + * \brief This function checks if the remaining size in a buffer is + * greater or equal than a needed space. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + * \return Zero if the needed space is available in the buffer, non-zero + * otherwise. + */ +static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur, + const uint8_t *end, size_t need ) +{ + return( ( cur > end ) || ( need > (size_t)( end - cur ) ) ); +} + +/** + * \brief This macro checks if the remaining size in a buffer is + * greater or equal than a needed space. If it is not the case, + * it returns an SSL_BUFFER_TOO_SMALL error. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_PTR( cur, end, need ) \ + do { \ + if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 ) \ + { \ + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); \ + } \ + } while( 0 ) + #ifdef __cplusplus extern "C" { #endif diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h index 774a007a9f..ac3be04337 100644 --- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h +++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_SSL_TICKET_H diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h index 92e6e6b987..b6ec4df8e9 100644 --- a/thirdparty/mbedtls/include/mbedtls/threading.h +++ b/thirdparty/mbedtls/include/mbedtls/threading.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_THREADING_H diff --git a/thirdparty/mbedtls/include/mbedtls/timing.h b/thirdparty/mbedtls/include/mbedtls/timing.h index a965fe0d35..149ccfb666 100644 --- a/thirdparty/mbedtls/include/mbedtls/timing.h +++ b/thirdparty/mbedtls/include/mbedtls/timing.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_TIMING_H diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index e0a2e7f6d6..2bff31d51f 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* @@ -40,16 +67,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 16 -#define MBEDTLS_VERSION_PATCH 6 +#define MBEDTLS_VERSION_PATCH 7 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02100600 -#define MBEDTLS_VERSION_STRING "2.16.6" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.6" +#define MBEDTLS_VERSION_NUMBER 0x02100700 +#define MBEDTLS_VERSION_STRING "2.16.7" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.7" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/include/mbedtls/x509.h b/thirdparty/mbedtls/include/mbedtls/x509.h index 63aae32d87..e9f2fc6024 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509.h +++ b/thirdparty/mbedtls/include/mbedtls/x509.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_H diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crl.h b/thirdparty/mbedtls/include/mbedtls/x509_crl.h index fa838d68cb..0e37f65e8f 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crl.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crl.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_CRL_H diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h index 670bd10d89..4aae923ea0 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_CRT_H diff --git a/thirdparty/mbedtls/include/mbedtls/x509_csr.h b/thirdparty/mbedtls/include/mbedtls/x509_csr.h index a3c28048e0..8ba2cda0dc 100644 --- a/thirdparty/mbedtls/include/mbedtls/x509_csr.h +++ b/thirdparty/mbedtls/include/mbedtls/x509_csr.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_X509_CSR_H diff --git a/thirdparty/mbedtls/include/mbedtls/xtea.h b/thirdparty/mbedtls/include/mbedtls/xtea.h index b47f553508..d372110215 100644 --- a/thirdparty/mbedtls/include/mbedtls/xtea.h +++ b/thirdparty/mbedtls/include/mbedtls/xtea.h @@ -5,7 +5,13 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -19,6 +25,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #ifndef MBEDTLS_XTEA_H diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c index 02a7986b59..9ec28690b2 100644 --- a/thirdparty/mbedtls/library/aes.c +++ b/thirdparty/mbedtls/library/aes.c @@ -2,7 +2,13 @@ * FIPS-197 compliant AES implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/aesni.c b/thirdparty/mbedtls/library/aesni.c index 062708b047..44bd89cba9 100644 --- a/thirdparty/mbedtls/library/aesni.c +++ b/thirdparty/mbedtls/library/aesni.c @@ -2,7 +2,13 @@ * AES-NI support functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/arc4.c b/thirdparty/mbedtls/library/arc4.c index b8998ac6cd..c30facb671 100644 --- a/thirdparty/mbedtls/library/arc4.c +++ b/thirdparty/mbedtls/library/arc4.c @@ -2,7 +2,13 @@ * An implementation of the ARCFOUR algorithm * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/aria.c b/thirdparty/mbedtls/library/aria.c index aff66d667f..0c9dd76f07 100644 --- a/thirdparty/mbedtls/library/aria.c +++ b/thirdparty/mbedtls/library/aria.c @@ -2,7 +2,13 @@ * ARIA implementation * * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/asn1parse.c b/thirdparty/mbedtls/library/asn1parse.c index 171c340b8c..8d59119ae0 100644 --- a/thirdparty/mbedtls/library/asn1parse.c +++ b/thirdparty/mbedtls/library/asn1parse.c @@ -2,7 +2,13 @@ * Generic ASN.1 parsing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c index c0b4622d58..bd0d6af4d8 100644 --- a/thirdparty/mbedtls/library/asn1write.c +++ b/thirdparty/mbedtls/library/asn1write.c @@ -2,7 +2,13 @@ * ASN.1 buffer writing functionality * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c index f06b57b31f..75849d1214 100644 --- a/thirdparty/mbedtls/library/base64.c +++ b/thirdparty/mbedtls/library/base64.c @@ -2,7 +2,13 @@ * RFC 1521 base64 encoding/decoding * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index 87ccf42fad..f42b97650f 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -2,7 +2,13 @@ * Multi-precision integer library * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -243,6 +270,22 @@ void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) } /* + * Conditionally assign dest = src, without leaking information + * about whether the assignment was made or not. + * dest and src must be arrays of limbs of size n. + * assign must be 0 or 1. + */ +static void mpi_safe_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char assign ) +{ + size_t i; + for( i = 0; i < n; i++ ) + dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign; +} + +/* * Conditionally assign X = Y, without leaking information * about whether the assignment was made or not. * (Leaking information about the respective sizes of X and Y is ok however.) @@ -261,10 +304,9 @@ int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned X->s = X->s * ( 1 - assign ) + Y->s * assign; - for( i = 0; i < Y->n; i++ ) - X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + mpi_safe_cond_assign( Y->n, X->p, Y->p, assign ); - for( ; i < X->n; i++ ) + for( i = Y->n; i < X->n; i++ ) X->p[i] *= ( 1 - assign ); cleanup: @@ -1249,10 +1291,24 @@ cleanup: return( ret ); } -/* - * Helper for mbedtls_mpi subtraction +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate d - s where d and s have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise). + * + * \param n Number of limbs of \p d and \p s. + * \param[in,out] d On input, the left operand. + * On output, the result of the subtraction: + * \param[in] s The right operand. + * + * \return 1 if `d < s`. + * 0 if `d >= s`. */ -static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *s ) { size_t i; mbedtls_mpi_uint c, z; @@ -1263,28 +1319,22 @@ static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) c = ( *d < *s ) + z; *d -= *s; } - while( c != 0 ) - { - z = ( *d < c ); *d -= c; - c = z; d++; - } + return( c ); } /* - * Unsigned subtraction: X = |A| - |B| (HAC 14.9) + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) */ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) { mbedtls_mpi TB; int ret; size_t n; + mbedtls_mpi_uint carry; MPI_VALIDATE_RET( X != NULL ); MPI_VALIDATE_RET( A != NULL ); MPI_VALIDATE_RET( B != NULL ); - if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - mbedtls_mpi_init( &TB ); if( X == B ) @@ -1307,7 +1357,18 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi if( B->p[n - 1] != 0 ) break; - mpi_sub_hlp( n, B->p, X->p ); + carry = mpi_sub_hlp( n, X->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + --X->p[n]; + } cleanup: @@ -1887,18 +1948,34 @@ static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) *mm = ~x + 1; } -/* - * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. */ -static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) { size_t i, n, m; mbedtls_mpi_uint u0, u1, *d; - if( T->n < N->n + 1 || T->p == NULL ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - memset( T->p, 0, T->n * ciL ); d = T->p; @@ -1919,22 +1996,34 @@ static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *d++ = u0; d[n + 1] = 0; } - memcpy( A->p, d, ( n + 1 ) * ciL ); - - if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) - mpi_sub_hlp( n, N->p, A->p ); - else - /* prevent timing attacks */ - mpi_sub_hlp( n, A->p, T->p ); - - return( 0 ); + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] ); } /* * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. */ -static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, - mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) { mbedtls_mpi_uint z = 1; mbedtls_mpi U; @@ -1942,7 +2031,7 @@ static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, U.n = U.s = (int) z; U.p = &z; - return( mpi_montmul( A, &U, N, mm, T ) ); + mpi_montmul( A, &U, N, mm, T ); } /* @@ -2028,13 +2117,13 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, else MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); - MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); + mpi_montmul( &W[1], &RR, N, mm, &T ); /* * X = R^2 * R^-1 mod N = R mod N */ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + mpi_montred( X, N, mm, &T ); if( wsize > 1 ) { @@ -2047,7 +2136,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); for( i = 0; i < wsize - 1; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); + mpi_montmul( &W[j], &W[j], N, mm, &T ); /* * W[i] = W[i - 1] * W[1] @@ -2057,7 +2146,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); - MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); + mpi_montmul( &W[i], &W[1], N, mm, &T ); } } @@ -2094,7 +2183,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, /* * out of window, square X */ - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + mpi_montmul( X, X, N, mm, &T ); continue; } @@ -2112,12 +2201,12 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, * X = X^wsize R^-1 mod N */ for( i = 0; i < wsize; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + mpi_montmul( X, X, N, mm, &T ); /* * X = X * W[wbits] R^-1 mod N */ - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); + mpi_montmul( X, &W[wbits], N, mm, &T ); state--; nbits = 0; @@ -2130,18 +2219,18 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, */ for( i = 0; i < nbits; i++ ) { - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + mpi_montmul( X, X, N, mm, &T ); wbits <<= 1; if( ( wbits & ( one << wsize ) ) != 0 ) - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); + mpi_montmul( X, &W[1], N, mm, &T ); } /* * X = A^E * R * R^-1 mod N = A^E mod N */ - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + mpi_montred( X, N, mm, &T ); if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) { diff --git a/thirdparty/mbedtls/library/blowfish.c b/thirdparty/mbedtls/library/blowfish.c index cbf9238246..f11a9d6395 100644 --- a/thirdparty/mbedtls/library/blowfish.c +++ b/thirdparty/mbedtls/library/blowfish.c @@ -2,7 +2,13 @@ * Blowfish implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/camellia.c b/thirdparty/mbedtls/library/camellia.c index 22262b89a8..9f5724917b 100644 --- a/thirdparty/mbedtls/library/camellia.c +++ b/thirdparty/mbedtls/library/camellia.c @@ -2,7 +2,13 @@ * Camellia implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ccm.c b/thirdparty/mbedtls/library/ccm.c index c6211ee773..18a2343ac5 100644 --- a/thirdparty/mbedtls/library/ccm.c +++ b/thirdparty/mbedtls/library/ccm.c @@ -2,7 +2,13 @@ * NIST SP800-38C compliant CCM implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/certs.c b/thirdparty/mbedtls/library/certs.c index 80ab0b9d6c..7423168b25 100644 --- a/thirdparty/mbedtls/library/certs.c +++ b/thirdparty/mbedtls/library/certs.c @@ -2,7 +2,13 @@ * X.509 test certificates * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/chacha20.c b/thirdparty/mbedtls/library/chacha20.c index 8a3610f0e0..d851a25bd6 100644 --- a/thirdparty/mbedtls/library/chacha20.c +++ b/thirdparty/mbedtls/library/chacha20.c @@ -6,7 +6,13 @@ * \author Daniel King <damaki.gh@gmail.com> * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/chachapoly.c b/thirdparty/mbedtls/library/chachapoly.c index dc643dd618..f232190dfc 100644 --- a/thirdparty/mbedtls/library/chachapoly.c +++ b/thirdparty/mbedtls/library/chachapoly.c @@ -4,7 +4,13 @@ * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -18,6 +24,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c index 8d010b59ac..896ec8ec66 100644 --- a/thirdparty/mbedtls/library/cipher.c +++ b/thirdparty/mbedtls/library/cipher.c @@ -6,7 +6,13 @@ * \author Adriaan de Jong <dejong@fox-it.com> * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/cipher_wrap.c b/thirdparty/mbedtls/library/cipher_wrap.c index 6dd8c5d3a9..09296c7f9b 100644 --- a/thirdparty/mbedtls/library/cipher_wrap.c +++ b/thirdparty/mbedtls/library/cipher_wrap.c @@ -6,7 +6,13 @@ * \author Adriaan de Jong <dejong@fox-it.com> * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/cmac.c b/thirdparty/mbedtls/library/cmac.c index 5d101e1c7d..ce0cd4b055 100644 --- a/thirdparty/mbedtls/library/cmac.c +++ b/thirdparty/mbedtls/library/cmac.c @@ -4,7 +4,13 @@ * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -18,6 +24,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c index ad0a1936d1..e1900afc45 100644 --- a/thirdparty/mbedtls/library/ctr_drbg.c +++ b/thirdparty/mbedtls/library/ctr_drbg.c @@ -2,7 +2,13 @@ * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/debug.c b/thirdparty/mbedtls/library/debug.c index 36510cdd56..3604cfb253 100644 --- a/thirdparty/mbedtls/library/debug.c +++ b/thirdparty/mbedtls/library/debug.c @@ -2,7 +2,13 @@ * Debugging routines * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/des.c b/thirdparty/mbedtls/library/des.c index 8a33d82e50..a5f73330b0 100644 --- a/thirdparty/mbedtls/library/des.c +++ b/thirdparty/mbedtls/library/des.c @@ -2,7 +2,13 @@ * FIPS-46-3 compliant Triple-DES implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/dhm.c b/thirdparty/mbedtls/library/dhm.c index 8255632a99..f8d367ee89 100644 --- a/thirdparty/mbedtls/library/dhm.c +++ b/thirdparty/mbedtls/library/dhm.c @@ -2,7 +2,13 @@ * Diffie-Hellman-Merkle key exchange * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c index c5726877d5..5ef205f36d 100644 --- a/thirdparty/mbedtls/library/ecdh.c +++ b/thirdparty/mbedtls/library/ecdh.c @@ -2,7 +2,13 @@ * Elliptic curve Diffie-Hellman * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c index 6b72e0d927..08fda3fa9b 100644 --- a/thirdparty/mbedtls/library/ecdsa.c +++ b/thirdparty/mbedtls/library/ecdsa.c @@ -2,7 +2,13 @@ * Elliptic curve DSA * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c index 1845c936ab..c89163c68a 100644 --- a/thirdparty/mbedtls/library/ecjpake.c +++ b/thirdparty/mbedtls/library/ecjpake.c @@ -2,7 +2,13 @@ * Elliptic curve J-PAKE * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c index 725e176df2..7ea8b1676a 100644 --- a/thirdparty/mbedtls/library/ecp.c +++ b/thirdparty/mbedtls/library/ecp.c @@ -2,7 +2,13 @@ * Elliptic curves over GF(p): generic functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -104,6 +131,20 @@ #include "mbedtls/ecp_internal.h" +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#elif defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#elif defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#elif defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#else +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline @@ -117,6 +158,233 @@ static unsigned long add_count, dbl_count, mul_count; #endif +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +/* + * Currently ecp_mul() takes a RNG function as an argument, used for + * side-channel protection, but it can be NULL. The initial reasoning was + * that people will pass non-NULL RNG when they care about side-channels, but + * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with + * no opportunity for the user to do anything about it. + * + * The obvious strategies for addressing that include: + * - change those APIs so that they take RNG arguments; + * - require a global RNG to be available to all crypto modules. + * + * Unfortunately those would break compatibility. So what we do instead is + * have our own internal DRBG instance, seeded from the secret scalar. + * + * The following is a light-weight abstraction layer for doing that with + * HMAC_DRBG (first choice) or CTR_DRBG. + */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_hmac_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + /* The list starts with strong hashes */ + const mbedtls_md_type_t md_type = mbedtls_md_list()[0]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_CTR_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_ctr_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) ); +} + +/* + * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does, + * we need to pass an entropy function when seeding. So we use a dummy + * function for that, and pass the actual entropy as customisation string. + * (During seeding of CTR_DRBG the entropy input and customisation string are + * concatenated before being used to update the secret state.) + */ +static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len) +{ + (void) ctx; + memset( out, 0, len ); + return( 0 ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL, + secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C) + +/* This will be used in the self-test function */ +#define ECP_ONE_STEP_KDF + +/* + * We need to expand secret data (the scalar) into a longer stream of bytes. + * + * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash + * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for + * convenience, this is not a full-fledged DRBG, but we don't need one here.) + * + * We need a basic hash abstraction layer to use whatever SHA-2 is available. + */ +#if defined(MBEDTLS_SHA512_C) + +#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 ); +#define HASH_BLOCK_BYTES ( 512 / 8 ) + +#elif defined(MBEDTLS_SHA256_C) + +#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 ); +#define HASH_BLOCK_BYTES ( 256 / 8 ) + +#endif /* SHA512/SHA256 abstraction */ + +/* + * State consists of a 32-bit counter plus the secret value. + * + * We stored them concatenated in a single buffer as that's what will get + * passed to the hash function. + */ +typedef struct { + size_t total_len; + uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES]; +} ecp_drbg_context; + +static void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( ecp_drbg_context ) ); +} + +static void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) ); +} + +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + ctx->total_len = 4 + secret_len; + memset( ctx->buf, 0, 4); + return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) ); +} + +static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + ecp_drbg_context *ctx = p_rng; + int ret; + size_t len_done = 0; + uint8_t tmp[HASH_BLOCK_BYTES]; + + while( len_done < output_len ) + { + uint8_t use_len; + + /* This function is only called for coordinate randomisation, which + * happens only twice in a scalar multiplication. Each time needs a + * random value in the range [2, p-1], and gets it by drawing len(p) + * bytes from this function, and retrying up to 10 times if unlucky. + * + * So for the largest curve, each scalar multiplication draws at most + * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with + * rounding that means a most 20 * 3 blocks. + * + * Since we don't need to draw more that 255 blocks, don't bother + * with carry propagation and just return an error instead. We can + * change that it we even need to draw more blinding values. + */ + ctx->buf[3] += 1; + if( ctx->buf[3] == 0 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + + ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp ); + if( ret != 0 ) + return( ret ); + + if( output_len - len_done > HASH_BLOCK_BYTES ) + use_len = HASH_BLOCK_BYTES; + else + use_len = output_len - len_done; + + memcpy( output + len_done, tmp, use_len ); + len_done += use_len; + } + + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( 0 ); +} + +#else /* DRBG/SHA modules */ +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif /* DRBG/SHA modules */ +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Maximum number of "basic operations" to be done in a row. @@ -164,6 +432,10 @@ struct mbedtls_ecp_restart_mul ecp_rsm_comb_core, /* ecp_mul_comb_core() */ ecp_rsm_final_norm, /* do the final normalization */ } state; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + unsigned char drbg_seeded; +#endif }; /* @@ -176,6 +448,10 @@ static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) ctx->T = NULL; ctx->T_size = 0; ctx->state = ecp_rsm_init; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_init( &ctx->drbg_ctx ); + ctx->drbg_seeded = 0; +#endif } /* @@ -197,6 +473,10 @@ static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) mbedtls_free( ctx->T ); } +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &ctx->drbg_ctx ); +#endif + ecp_restart_rsm_init( ctx ); } @@ -1466,7 +1746,10 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); if( count++ > 10 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } } while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); @@ -1816,7 +2099,9 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R i = d; MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) if( f_rng != 0 ) +#endif MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); } @@ -1937,6 +2222,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, rs_ctx->rsm->state = ecp_rsm_final_norm; final_norm: + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); #endif /* * Knowledge of the jacobian coordinates may leak the last few bits of the @@ -1949,10 +2235,11 @@ final_norm: * * Avoid the leak by randomizing coordinates before we normalize them. */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) if( f_rng != 0 ) +#endif MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); - MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -2021,11 +2308,44 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, int ret; unsigned char w, p_eq_g, i; size_t d; - unsigned char T_size, T_ok; - mbedtls_ecp_point *T; + unsigned char T_size = 0, T_ok = 0; + mbedtls_ecp_point *T = NULL; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif ECP_RS_ENTER( rsm ); +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + /* Adjust pointers */ + f_rng = &ecp_drbg_random; +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + p_rng = &rs_ctx->rsm->drbg_ctx; + else +#endif + p_rng = &drbg_ctx; + + /* Initialize internal DRBG if necessary */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL || + rs_ctx->rsm->drbg_seeded == 0 ) +#endif + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) ); + } +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->drbg_seeded = 1; +#endif + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + /* Is P the base point ? */ #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && @@ -2097,6 +2417,10 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, cleanup: +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + /* does T belong to the group? */ if( T == grp->T ) T = NULL; @@ -2198,7 +2522,10 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); if( count++ > 10 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } } while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); @@ -2284,9 +2611,23 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, unsigned char b; mbedtls_ecp_point RP; mbedtls_mpi PX; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + ecp_drbg_init( &drbg_ctx ); +#endif mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) ); + f_rng = &ecp_drbg_random; + p_rng = &drbg_ctx; + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + /* Save PX and read from P before writing to R, in case P == R */ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); @@ -2300,7 +2641,9 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MOD_ADD( RP.X ); /* Randomize coordinates of the starting point */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) if( f_rng != NULL ) +#endif MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); /* Loop invariant: R = result so far, RP = R + P */ @@ -2333,12 +2676,18 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * * Avoid the leak by randomizing coordinates before we normalize them. */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) if( f_rng != NULL ) +#endif MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); cleanup: +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); return( ret ); @@ -2893,6 +3242,76 @@ cleanup: #if defined(MBEDTLS_SELF_TEST) +#if defined(ECP_ONE_STEP_KDF) +/* + * There are no test vectors from NIST for the One-Step KDF in SP 800-56C, + * but unofficial ones can be found at: + * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors + * + * We only use the ones with empty fixedInfo, and for brevity's sake, only + * 40-bytes output (with SHA-256 that's more than one block, and with SHA-512 + * less than one block). + */ +#if defined(MBEDTLS_SHA512_C) + +static const uint8_t test_kdf_z[16] = { + 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7, + 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa, +}; +static const uint8_t test_kdf_out[40] = { + 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f, + 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05, + 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25, + 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27, + 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa, +}; + +#elif defined(MBEDTLS_SHA256_C) + +static const uint8_t test_kdf_z[16] = { + 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6, + 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1, +}; +static const uint8_t test_kdf_out[40] = { + 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28, + 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25, + 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c, + 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66, + 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79, +}; + +#endif + +static int ecp_kdf_self_test( void ) +{ + int ret; + ecp_drbg_context kdf_ctx; + mbedtls_mpi scalar; + uint8_t out[sizeof( test_kdf_out )]; + + ecp_drbg_init( &kdf_ctx ); + mbedtls_mpi_init( &scalar ); + memset( out, 0, sizeof( out ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar, + test_kdf_z, sizeof( test_kdf_z ) ) ); + + MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx, + &scalar, sizeof( test_kdf_z ) ) ); + + MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) ); + + if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 ) + ret = -1; + +cleanup: + ecp_drbg_free( &kdf_ctx ); + mbedtls_mpi_free( &scalar ); + + return( ret ); +} +#endif /* ECP_ONE_STEP_KDF */ + /* * Checkup routine */ @@ -3004,6 +3423,24 @@ int mbedtls_ecp_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); +#if defined(ECP_ONE_STEP_KDF) + if( verbose != 0 ) + mbedtls_printf( " ECP test #3 (internal KDF): " ); + + ret = ecp_kdf_self_test(); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* ECP_ONE_STEP_KDF */ + cleanup: if( ret < 0 && verbose != 0 ) diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c index 282481d053..796e0d1250 100644 --- a/thirdparty/mbedtls/library/ecp_curves.c +++ b/thirdparty/mbedtls/library/ecp_curves.c @@ -2,7 +2,13 @@ * Elliptic curves over GF(p): curve-specific data and functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c index f8db1a5503..1bd6ce54ee 100644 --- a/thirdparty/mbedtls/library/entropy.c +++ b/thirdparty/mbedtls/library/entropy.c @@ -2,7 +2,13 @@ * Entropy accumulator implementation * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/entropy_poll.c b/thirdparty/mbedtls/library/entropy_poll.c index ba56b70f77..a5996a198d 100644 --- a/thirdparty/mbedtls/library/entropy_poll.c +++ b/thirdparty/mbedtls/library/entropy_poll.c @@ -2,7 +2,13 @@ * Platform-specific and custom entropy polling functions * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/error.c b/thirdparty/mbedtls/library/error.c index c596f0bcc5..4ab8733e0c 100644 --- a/thirdparty/mbedtls/library/error.c +++ b/thirdparty/mbedtls/library/error.c @@ -2,7 +2,13 @@ * Error message information * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -53,6 +80,10 @@ #include "mbedtls/aria.h" #endif +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" #endif @@ -525,6 +556,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) ) mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_CONFIG) ) + mbedtls_snprintf( buf, buflen, "SSL - Invalid value in SSL config" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) diff --git a/thirdparty/mbedtls/library/gcm.c b/thirdparty/mbedtls/library/gcm.c index 675926a518..7edc6da366 100644 --- a/thirdparty/mbedtls/library/gcm.c +++ b/thirdparty/mbedtls/library/gcm.c @@ -2,7 +2,13 @@ * NIST SP800-38D compliant GCM implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/havege.c b/thirdparty/mbedtls/library/havege.c index c139e1db03..800a518a66 100644 --- a/thirdparty/mbedtls/library/havege.c +++ b/thirdparty/mbedtls/library/havege.c @@ -2,7 +2,13 @@ * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/hkdf.c b/thirdparty/mbedtls/library/hkdf.c index 82d8a429f4..0dd4d05645 100644 --- a/thirdparty/mbedtls/library/hkdf.c +++ b/thirdparty/mbedtls/library/hkdf.c @@ -2,7 +2,13 @@ * HKDF implementation -- RFC 5869 * * Copyright (C) 2016-2018, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c index 284c9b4e96..2cb108c406 100644 --- a/thirdparty/mbedtls/library/hmac_drbg.c +++ b/thirdparty/mbedtls/library/hmac_drbg.c @@ -2,7 +2,13 @@ * HMAC_DRBG implementation (NIST SP 800-90) * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/md.c b/thirdparty/mbedtls/library/md.c index 303cdcbeeb..bfada3c058 100644 --- a/thirdparty/mbedtls/library/md.c +++ b/thirdparty/mbedtls/library/md.c @@ -6,7 +6,13 @@ * \author Adriaan de Jong <dejong@fox-it.com> * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/md2.c b/thirdparty/mbedtls/library/md2.c index 1c0b3df52d..d772039b79 100644 --- a/thirdparty/mbedtls/library/md2.c +++ b/thirdparty/mbedtls/library/md2.c @@ -2,7 +2,13 @@ * RFC 1115/1319 compliant MD2 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/md4.c b/thirdparty/mbedtls/library/md4.c index 828fd42999..56b359ce34 100644 --- a/thirdparty/mbedtls/library/md4.c +++ b/thirdparty/mbedtls/library/md4.c @@ -2,7 +2,13 @@ * RFC 1186/1320 compliant MD4 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/md5.c b/thirdparty/mbedtls/library/md5.c index a93da8a061..31879a9b14 100644 --- a/thirdparty/mbedtls/library/md5.c +++ b/thirdparty/mbedtls/library/md5.c @@ -2,7 +2,13 @@ * RFC 1321 compliant MD5 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/md_wrap.c b/thirdparty/mbedtls/library/md_wrap.c index 32f0871976..7c737d87e9 100644 --- a/thirdparty/mbedtls/library/md_wrap.c +++ b/thirdparty/mbedtls/library/md_wrap.c @@ -6,7 +6,13 @@ * \author Adriaan de Jong <dejong@fox-it.com> * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/memory_buffer_alloc.c b/thirdparty/mbedtls/library/memory_buffer_alloc.c index 51ea7c41d7..e854eea8ee 100644 --- a/thirdparty/mbedtls/library/memory_buffer_alloc.c +++ b/thirdparty/mbedtls/library/memory_buffer_alloc.c @@ -2,7 +2,13 @@ * Buffer-based memory allocator * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 5d538bfd56..9489576aae 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -2,7 +2,13 @@ * TCP/IP or UDP/IP networking functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/nist_kw.c b/thirdparty/mbedtls/library/nist_kw.c index 317a2426ae..35be530957 100644 --- a/thirdparty/mbedtls/library/nist_kw.c +++ b/thirdparty/mbedtls/library/nist_kw.c @@ -3,7 +3,13 @@ * only * * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -17,6 +23,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/oid.c b/thirdparty/mbedtls/library/oid.c index 33f437cbe6..0a1658f821 100644 --- a/thirdparty/mbedtls/library/oid.c +++ b/thirdparty/mbedtls/library/oid.c @@ -4,7 +4,13 @@ * \brief Object Identifier (OID) database * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -18,6 +24,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/padlock.c b/thirdparty/mbedtls/library/padlock.c index b85ff9cd2c..fe6e7f9cf3 100644 --- a/thirdparty/mbedtls/library/padlock.c +++ b/thirdparty/mbedtls/library/padlock.c @@ -2,7 +2,13 @@ * VIA PadLock support functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/pem.c b/thirdparty/mbedtls/library/pem.c index 897c8a0d6f..3bf4ca5b8c 100644 --- a/thirdparty/mbedtls/library/pem.c +++ b/thirdparty/mbedtls/library/pem.c @@ -2,7 +2,13 @@ * Privacy Enhanced Mail (PEM) decoding * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/pk.c b/thirdparty/mbedtls/library/pk.c index bac685dc19..e9e56c029b 100644 --- a/thirdparty/mbedtls/library/pk.c +++ b/thirdparty/mbedtls/library/pk.c @@ -2,7 +2,13 @@ * Public Key abstraction layer * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/pk_wrap.c b/thirdparty/mbedtls/library/pk_wrap.c index 87806be337..21a7a33d82 100644 --- a/thirdparty/mbedtls/library/pk_wrap.c +++ b/thirdparty/mbedtls/library/pk_wrap.c @@ -2,7 +2,13 @@ * Public Key abstraction layer: wrapper functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/pkcs11.c b/thirdparty/mbedtls/library/pkcs11.c index 0ea64252ee..30d045bf18 100644 --- a/thirdparty/mbedtls/library/pkcs11.c +++ b/thirdparty/mbedtls/library/pkcs11.c @@ -6,7 +6,13 @@ * \author Adriaan de Jong <dejong@fox-it.com> * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/pkcs12.c b/thirdparty/mbedtls/library/pkcs12.c index 7edf064c13..3c34128682 100644 --- a/thirdparty/mbedtls/library/pkcs12.c +++ b/thirdparty/mbedtls/library/pkcs12.c @@ -2,7 +2,13 @@ * PKCS#12 Personal Information Exchange Syntax * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/pkcs5.c b/thirdparty/mbedtls/library/pkcs5.c index 50133435ce..7ac67093c0 100644 --- a/thirdparty/mbedtls/library/pkcs5.c +++ b/thirdparty/mbedtls/library/pkcs5.c @@ -6,7 +6,13 @@ * \author Mathias Olsson <mathias@kompetensum.com> * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -20,6 +26,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c index d5004577a1..624ca4c671 100644 --- a/thirdparty/mbedtls/library/pkparse.c +++ b/thirdparty/mbedtls/library/pkparse.c @@ -2,7 +2,13 @@ * Public Key layer for parsing key files and structures * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c index 03d14f2ff9..76159e5a80 100644 --- a/thirdparty/mbedtls/library/pkwrite.c +++ b/thirdparty/mbedtls/library/pkwrite.c @@ -2,7 +2,13 @@ * Public Key layer for writing key files and structures * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/platform.c b/thirdparty/mbedtls/library/platform.c index 73a6db9ebe..7fe5e56b71 100644 --- a/thirdparty/mbedtls/library/platform.c +++ b/thirdparty/mbedtls/library/platform.c @@ -2,7 +2,13 @@ * Platform abstraction layer * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/platform_util.c b/thirdparty/mbedtls/library/platform_util.c index b1f745097c..c31c173c89 100644 --- a/thirdparty/mbedtls/library/platform_util.c +++ b/thirdparty/mbedtls/library/platform_util.c @@ -3,7 +3,13 @@ * library. * * Copyright (C) 2018, Arm Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -17,6 +23,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of Mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/poly1305.c b/thirdparty/mbedtls/library/poly1305.c index 2b56c5f7ef..295997f2bc 100644 --- a/thirdparty/mbedtls/library/poly1305.c +++ b/thirdparty/mbedtls/library/poly1305.c @@ -4,7 +4,13 @@ * \brief Poly1305 authentication algorithm. * * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -18,6 +24,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ #if !defined(MBEDTLS_CONFIG_FILE) diff --git a/thirdparty/mbedtls/library/ripemd160.c b/thirdparty/mbedtls/library/ripemd160.c index 0791ae4cc9..721db1efe4 100644 --- a/thirdparty/mbedtls/library/ripemd160.c +++ b/thirdparty/mbedtls/library/ripemd160.c @@ -2,7 +2,13 @@ * RIPE MD-160 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c index 09fd379fdb..af1cef6515 100644 --- a/thirdparty/mbedtls/library/rsa.c +++ b/thirdparty/mbedtls/library/rsa.c @@ -2,7 +2,13 @@ * The RSA public-key cryptosystem * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/rsa_internal.c b/thirdparty/mbedtls/library/rsa_internal.c index 9a42d47ceb..4db49aa578 100644 --- a/thirdparty/mbedtls/library/rsa_internal.c +++ b/thirdparty/mbedtls/library/rsa_internal.c @@ -2,7 +2,13 @@ * Helper functions for the RSA module * * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) * */ diff --git a/thirdparty/mbedtls/library/sha1.c b/thirdparty/mbedtls/library/sha1.c index 355c83d2f7..1cffc75f8c 100644 --- a/thirdparty/mbedtls/library/sha1.c +++ b/thirdparty/mbedtls/library/sha1.c @@ -2,7 +2,13 @@ * FIPS-180-1 compliant SHA-1 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/sha256.c b/thirdparty/mbedtls/library/sha256.c index 2dc0e1a2c9..d4dd4859a6 100644 --- a/thirdparty/mbedtls/library/sha256.c +++ b/thirdparty/mbedtls/library/sha256.c @@ -2,7 +2,13 @@ * FIPS-180-2 compliant SHA-256 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/sha512.c b/thirdparty/mbedtls/library/sha512.c index bdd20b284a..fdcf360d3f 100644 --- a/thirdparty/mbedtls/library/sha512.c +++ b/thirdparty/mbedtls/library/sha512.c @@ -2,7 +2,13 @@ * FIPS-180-2 compliant SHA-384/512 implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ssl_cache.c b/thirdparty/mbedtls/library/ssl_cache.c index 47867f132d..3cbfeb740a 100644 --- a/thirdparty/mbedtls/library/ssl_cache.c +++ b/thirdparty/mbedtls/library/ssl_cache.c @@ -2,7 +2,13 @@ * SSL session cache implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c index 518f7dde00..de566ebca9 100644 --- a/thirdparty/mbedtls/library/ssl_ciphersuites.c +++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c @@ -4,7 +4,13 @@ * \brief SSL ciphersuites for mbed TLS * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -18,6 +24,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c index c5c3af69df..9fb2eceb22 100644 --- a/thirdparty/mbedtls/library/ssl_cli.c +++ b/thirdparty/mbedtls/library/ssl_cli.c @@ -2,7 +2,13 @@ * SSLv3/TLSv1 client-side functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -52,29 +79,26 @@ #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) +static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t hostname_len; *olen = 0; if( ssl->hostname == NULL ) - return; + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", - ssl->hostname ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding server name extension: %s", + ssl->hostname ) ); hostname_len = strlen( ssl->hostname ); - if( end < p || (size_t)( end - p ) < hostname_len + 9 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 ); /* * Sect. 3, RFC 6066 (TLS Extensions Definitions) @@ -118,16 +142,18 @@ static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, memcpy( p, ssl->hostname, hostname_len ); *olen = hostname_len + 9; + + return( 0 ); } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_RENEGOTIATION) -static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) +static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; @@ -135,21 +161,20 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, * initial ClientHello, in which case also adding the renegotiation * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - return; + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding renegotiation extension" ) ); - if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len ); /* * Secure renegotiation */ - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) + & 0xFF ); *p++ = 0x00; *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; @@ -158,6 +183,8 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); *olen = 5 + ssl->verify_data_len; + + return( 0 ); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -166,14 +193,15 @@ static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) +static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t sig_alg_len = 0; const int *md; + #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) unsigned char *sig_alg_list = buf + 6; #endif @@ -181,9 +209,13 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, *olen = 0; if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - return; + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding signature_algorithms extension" ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); + if( ssl->conf->sig_hashes == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) { @@ -193,13 +225,19 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_RSA_C) sig_alg_len += 2; #endif + if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "length in bytes of sig-hash-alg extension too big" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } } - if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + /* Empty signature algorithms list, this is a configuration error. */ + if( sig_alg_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 ); /* * Prepare signature_algorithms extension (TLS 1.2) @@ -245,75 +283,75 @@ static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); *olen = 6 + sig_alg_len; + + return( 0 ); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) +static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; unsigned char *elliptic_curve_list = p + 6; size_t elliptic_curve_len = 0; const mbedtls_ecp_curve_info *info; -#if defined(MBEDTLS_ECP_C) const mbedtls_ecp_group_id *grp_id; -#else - ((void) ssl); -#endif *olen = 0; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_elliptic_curves extension" ) ); -#if defined(MBEDTLS_ECP_C) - for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) -#else - for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) -#endif + if( ssl->conf->curve_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) { -#if defined(MBEDTLS_ECP_C) info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); -#endif if( info == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) ); - return; + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "invalid curve in ssl configuration" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); } - elliptic_curve_len += 2; - } - if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; + if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "malformed supported_elliptic_curves extension in config" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } } + /* Empty elliptic curve list, this is a configuration error. */ + if( elliptic_curve_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + elliptic_curve_len ); + elliptic_curve_len = 0; -#if defined(MBEDTLS_ECP_C) - for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) -#else - for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) -#endif + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) { -#if defined(MBEDTLS_ECP_C) info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); -#endif elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; } - if( elliptic_curve_len == 0 ) - return; - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) + & 0xFF ); *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); @@ -322,27 +360,28 @@ static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); *olen = 6 + elliptic_curve_len; + + return( 0 ); } -static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) +static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + (void) ssl; /* ssl used for debugging only */ *olen = 0; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); - - if( end < p || (size_t)( end - p ) < 6 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_point_formats extension" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) + & 0xFF ); *p++ = 0x00; *p++ = 2; @@ -351,33 +390,32 @@ static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; *olen = 6; + + return( 0 ); } #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) +static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { int ret; unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; /* Skip costly extension if we can't use EC J-PAKE anyway */ if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - return; + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding ecjpake_kkpp extension" ) ); - if( end - p < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); @@ -393,19 +431,20 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, - p + 2, end - p - 2, &kkpp_len, - ssl->conf->f_rng, ssl->conf->p_rng ); + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); - return; + MBEDTLS_SSL_DEBUG_RET( 1 , + "mbedtls_ecjpake_write_round_one", ret ); + return( ret ); } ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); if( ssl->handshake->ecjpake_cache == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); - return; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); @@ -416,12 +455,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); kkpp_len = ssl->handshake->ecjpake_cache_len; - - if( (size_t)( end - p - 2 ) < kkpp_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len ); memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); } @@ -430,33 +464,33 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); *olen = kkpp_len + 4; + + return( 0 ); } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) +static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; - if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) { - return; - } + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding max_fragment_length extension" ) ); - if( end < p || (size_t)( end - p ) < 5 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) + & 0xFF ); *p++ = 0x00; *p++ = 1; @@ -464,30 +498,28 @@ static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, *p++ = ssl->conf->mfl_code; *olen = 5; + + return( 0 ); } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) +static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) - { - return; - } + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding truncated_hmac extension" ) ); - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); @@ -496,32 +528,29 @@ static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, *p++ = 0x00; *olen = 4; + + return( 0 ); } #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) +static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - return; - } + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " - "extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding encrypt_then_mac extension" ) ); - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); @@ -530,65 +559,63 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, *p++ = 0x00; *olen = 4; + + return( 0 ); } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) +static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - return; - } + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " - "extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding extended_master_secret extension" ) ); - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) + & 0xFF ); + *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) + & 0xFF ); *p++ = 0x00; *p++ = 0x00; *olen = 4; + + return( 0 ); } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) -static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) +static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t tlen = ssl->session_negotiate->ticket_len; *olen = 0; if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) - { - return; - } + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding session ticket extension" ) ); - if( end < p || (size_t)( end - p ) < 4 + tlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + /* The addition is safe here since the ticket length is 16 bit. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); @@ -599,44 +626,40 @@ static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, *olen = 4; if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) - { - return; - } + return( 0 ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "sending session ticket of length %d", tlen ) ); memcpy( p, ssl->session_negotiate->ticket, tlen ); *olen += tlen; + + return( 0 ); } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_ALPN) -static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) +static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) { unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t alpnlen = 0; const char **cur; *olen = 0; if( ssl->conf->alpn_list == NULL ) - { - return; - } + return( 0 ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) - alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1; + alpnlen += strlen( *cur ) + 1; - if( end < p || (size_t)( end - p ) < 6 + alpnlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); @@ -654,7 +677,11 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) { - *p = (unsigned char)( strlen( *cur ) & 0xFF ); + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + *p = (unsigned char)strlen( *cur ); memcpy( p + 1, *cur, *p ); p += 1 + *p; } @@ -668,6 +695,8 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); + + return( 0 ); } #endif /* MBEDTLS_SSL_ALPN */ @@ -724,9 +753,10 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) * * \return 0 if valid, else 1 */ -static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_info, - const mbedtls_ssl_context * ssl, - int min_minor_ver, int max_minor_ver ) +static int ssl_validate_ciphersuite( + const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) { (void) ssl; if( suite_info == NULL ) @@ -761,8 +791,11 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { int ret; size_t i, n, olen, ext_len = 0; + unsigned char *buf; unsigned char *p, *q; + const unsigned char *end; + unsigned char offer_compress; const int *ciphersuites; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; @@ -789,23 +822,41 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) if( ssl->conf->max_major_ver == 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, " - "consider using mbedtls_ssl_config_defaults()" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } + buf = ssl->out_msg; + end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN; + /* - * 0 . 0 handshake type - * 1 . 3 handshake length + * Check if there's enough space for the first part of the ClientHello + * consisting of the 38 bytes described below, the session identifier (at + * most 32 bytes) and its length (1 byte). + * + * Use static upper bounds instead of the actual values + * to allow the compiler to optimize this away. + */ + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 ); + + /* + * The 38 first bytes of the ClientHello: + * 0 . 0 handshake type (written later) + * 1 . 3 handshake length (written later) * 4 . 5 highest version supported * 6 . 9 current UNIX time * 10 . 37 random bytes + * + * The current UNIX time (4 bytes) and following 28 random bytes are written + * by ssl_generate_random() into ssl->handshake->randbytes buffer and then + * copied from there into the output buffer. */ - buf = ssl->out_msg; - p = buf + 4; - mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, - ssl->conf->transport, p ); + p = buf + 4; + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); p += 2; MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", @@ -825,7 +876,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) * 38 . 38 session id length * 39 . 39+n session id * 39+n . 39+n DTLS only: cookie length (1 byte) - * 40+n . .. DTSL only: cookie + * 40+n . .. DTLS only: cookie * .. . .. ciphersuitelist length (2 bytes) * .. . .. ciphersuitelist * .. . .. compression methods length (1 byte) @@ -856,7 +907,8 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) if( ssl->session_negotiate->ticket != NULL && ssl->session_negotiate->ticket_len != 0 ) { - ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 ); + ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ); if( ret != 0 ) return( ret ); @@ -866,6 +918,12 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ + /* + * The first check of the output buffer size above ( + * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );) + * has checked that there is enough space in the output buffer for the + * session identifier length byte and the session identifier (n <= 32). + */ *p++ = (unsigned char) n; for( i = 0; i < n; i++ ) @@ -875,11 +933,26 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); /* + * With 'n' being the length of the session identifier + * + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + + /* * DTLS cookie */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + if( ssl->handshake->verify_cookie == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); @@ -892,6 +965,9 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ssl->handshake->verify_cookie_len ); *p++ = ssl->handshake->verify_cookie_len; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, + ssl->handshake->verify_cookie_len ); memcpy( p, ssl->handshake->verify_cookie, ssl->handshake->verify_cookie_len ); p += ssl->handshake->verify_cookie_len; @@ -907,6 +983,8 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) /* Skip writing ciphersuite length for now */ n = 0; q = p; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); p += 2; for( i = 0; ciphersuites[i] != 0; i++ ) @@ -926,12 +1004,15 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); #endif + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + n++; *p++ = (unsigned char)( ciphersuites[i] >> 8 ); *p++ = (unsigned char)( ciphersuites[i] ); } - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, got %d ciphersuites (excluding SCSVs)", n ) ); /* * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV @@ -941,6 +1022,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) #endif { MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); n++; @@ -951,6 +1033,8 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); n++; @@ -981,8 +1065,10 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", - MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) ); + MBEDTLS_SSL_COMPRESS_DEFLATE, + MBEDTLS_SSL_COMPRESS_NULL ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 3 ); *p++ = 2; *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; *p++ = MBEDTLS_SSL_COMPRESS_NULL; @@ -993,27 +1079,45 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", MBEDTLS_SSL_COMPRESS_NULL ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); *p++ = 1; *p++ = MBEDTLS_SSL_COMPRESS_NULL; } - // First write extensions, then the total length - // + /* First write extensions, then the total length */ + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_hostname_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_hostname_ext", ret ); + return( ret ); + } ext_len += olen; #endif /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret ); + return( ret ); + } ext_len += olen; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret ); + return( ret ); + } ext_len += olen; #endif @@ -1021,46 +1125,91 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( uses_ec ) { - ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret ); + return( ret ); + } ext_len += olen; - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret ); + return( ret ); + } ext_len += olen; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret ); + return( ret ); + } ext_len += olen; #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret ); + return( ret ); + } ext_len += olen; #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_truncated_hmac_ext", ret ); + return( ret ); + } ext_len += olen; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret ); + return( ret ); + } ext_len += olen; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret ); + return( ret ); + } ext_len += olen; #endif #if defined(MBEDTLS_SSL_ALPN) - ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret ); + return( ret ); + } ext_len += olen; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) - ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret ); + return( ret ); + } ext_len += olen; #endif @@ -1068,10 +1217,12 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) ((void) olen); MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", - ext_len ) ); + ext_len ) ); if( ext_len > 0 ) { + /* No need to check for space here, because the extension + * writing functions already took care of that. */ *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( ext_len ) & 0xFF ); p += ext_len; @@ -1124,8 +1275,10 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } } @@ -1134,9 +1287,12 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, { if( len != 1 || buf[0] != 0x00 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1159,9 +1315,12 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, len != 1 || buf[0] != ssl->conf->mfl_code ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1177,9 +1336,12 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || len != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1200,9 +1362,12 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1223,9 +1388,12 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || len != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1245,9 +1413,12 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || len != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1328,8 +1499,10 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, buf, len ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( ret ); } @@ -1348,8 +1521,10 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, if( ssl->conf->alpn_list == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1529,12 +1704,13 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ssl->conf->renego_max_records >= 0 && ssl->renego_records_seen > ssl->conf->renego_max_records ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " - "but not honored by server" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation requested, but not honored by server" ) ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-handshake message during renegotiation" ) ); ssl->keep_current_message = 1; return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); @@ -1542,8 +1718,10 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_RENEGOTIATION */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -1597,11 +1775,13 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ssl->major_ver > ssl->conf->max_major_ver || ssl->minor_ver > ssl->conf->max_minor_ver ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - " - " min: [%d:%d], server: [%d:%d], max: [%d:%d]", - ssl->conf->min_major_ver, ssl->conf->min_minor_ver, - ssl->major_ver, ssl->minor_ver, - ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server version out of bounds - min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, + ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, + ssl->conf->max_minor_ver ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); @@ -1638,8 +1818,10 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } } @@ -1678,26 +1860,32 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( comp != MBEDTLS_SSL_COMPRESS_NULL ) #endif/* MBEDTLS_ZLIB_SUPPORT */ { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); } /* * Initialize update checksum functions */ - ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); + ssl->transform_negotiate->ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( i ); if( ssl->transform_negotiate->ciphersuite_info == NULL ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "ciphersuite info for %04x not found", i ) ); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); + mbedtls_ssl_optimize_checksum( ssl, + ssl->transform_negotiate->ciphersuite_info ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); @@ -1731,8 +1919,10 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); return( ret ); } } @@ -1741,7 +1931,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ssl->handshake->resume ? "a" : "no" ) ); MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", + buf[37 + n] ) ); /* * Perform cipher suite validation in same way as in ssl_write_client_hello. @@ -1752,8 +1943,10 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1764,16 +1957,21 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } } - suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); - if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, ssl->minor_ver ) != 0 ) + suite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, + ssl->minor_ver ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && @@ -1790,15 +1988,18 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } ssl->session_negotiate->compression = comp; ext = buf + 40 + n; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "server hello, total extension length: %d", ext_len ) ); while( ext_len ) { @@ -1810,8 +2011,9 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( ext_size + 4 > ext_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + mbedtls_ssl_send_alert_message( + ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1831,7 +2033,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found max_fragment_length extension" ) ); if( ( ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ) ) != 0 ) @@ -1870,7 +2073,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found extended_master_secret extension" ) ); if( ( ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ) ) != 0 ) @@ -1897,7 +2101,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found supported_point_formats extension" ) ); if( ( ret = ssl_parse_supported_point_formats_ext( ssl, ext + 4, ext_size ) ) != 0 ) @@ -1933,8 +2138,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_ALPN */ default: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", - ext_id ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "unknown extension found: %d (ignoring)", ext_id ) ); } ext_len -= 4 + ext_size; @@ -1951,9 +2156,11 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) * Renegotiation security checks */ if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "legacy renegotiation, breaking off handshake" ) ); handshake_failure = 1; } #if defined(MBEDTLS_SSL_RENEGOTIATION) @@ -1961,12 +2168,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && renegotiation_info_seen == 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension missing (secure)" ) ); handshake_failure = 1; } else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); handshake_failure = 1; @@ -1975,15 +2184,18 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && renegotiation_info_seen == 1 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension present (legacy)" ) ); handshake_failure = 1; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ if( handshake_failure == 1 ) { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); } @@ -1994,7 +2206,8 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, + unsigned char **p, unsigned char *end ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; @@ -2008,7 +2221,8 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char * * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ - if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, + p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); return( ret ); @@ -2104,7 +2318,8 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, if( ssl_check_server_ecdh_params( ssl ) != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (ECDHE curve)" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2130,8 +2345,8 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, */ if( end - (*p) < 2 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " - "(psk_identity_hint length)" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } len = (*p)[0] << 8 | (*p)[1]; @@ -2139,8 +2354,8 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, if( end - (*p) < (int) len ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " - "(psk_identity_hint length)" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2182,8 +2397,9 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, * opaque random[46]; * } PreMasterSecret; */ - mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, - ssl->conf->transport, p ); + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) { @@ -2260,20 +2476,22 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, /* * Get hash algorithm */ - if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE ) + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) + == MBEDTLS_MD_NONE ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported " - "HashAlgorithm %d", *(p)[0] ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } /* * Get signature algorithm */ - if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE ) + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) + == MBEDTLS_PK_NONE ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported " - "SignatureAlgorithm %d", (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2282,13 +2500,15 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, */ if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered", - *(p)[0] ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", + (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", + (*p)[0] ) ); *p += 2; return( 0 ); @@ -2366,8 +2586,10 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( ret ); } @@ -2397,8 +2619,10 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2417,10 +2641,12 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) goto exit; } - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must " - "not be skipped" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server key exchange message must not be skipped" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2444,8 +2670,10 @@ start_processing: if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } /* FALLTROUGH */ @@ -2467,8 +2695,10 @@ start_processing: if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2485,8 +2715,10 @@ start_processing: if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2502,8 +2734,10 @@ start_processing: if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2534,17 +2768,24 @@ start_processing: if( ssl_parse_signature_algorithm( ssl, &p, end, &md_alg, &pk_alg ) != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } - if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + if( pk_alg != + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } } @@ -2574,8 +2815,10 @@ start_processing: if( p > end - 2 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } sig_len = ( p[0] << 8 ) | p[1]; @@ -2584,8 +2827,10 @@ start_processing: if( p != end - sig_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); } @@ -2630,19 +2875,24 @@ start_processing: if( ssl->session_negotiate->peer_cert == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } /* * Verify signature */ - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) + if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, + pk_alg ) ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } @@ -2658,8 +2908,10 @@ start_processing: #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) #endif - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) @@ -2724,8 +2976,10 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } @@ -2801,8 +3055,9 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { - size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) - | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + size_t sig_alg_len = + ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); #if defined(MBEDTLS_DEBUG_C) unsigned char* sig_alg; size_t i; @@ -2820,11 +3075,14 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) * buf[...hdr_len + 3 + n + sig_alg_len], * which is one less than we need the buf to be. */ - if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n + sig_alg_len ) + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + + 3 + n + sig_alg_len ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); } @@ -2832,8 +3090,9 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; for( i = 0; i < sig_alg_len; i += 2 ) { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" - ",%d", sig_alg[i], sig_alg[i + 1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "Supported Signature Algorithm found: %d,%d", + sig_alg[i], sig_alg[i + 1] ) ); } #endif @@ -2922,9 +3181,9 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 6; ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - &ssl->out_msg[i], n, - ssl->conf->f_rng, ssl->conf->p_rng ); + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[i], n, + ssl->conf->f_rng, ssl->conf->p_rng ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); @@ -2935,10 +3194,10 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, - ssl->handshake->premaster, - MBEDTLS_PREMASTER_SIZE, - &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); return( ret ); @@ -3001,10 +3260,10 @@ ecdh_calc_secret: n = ssl->handshake->ecrs_n; #endif if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, - &ssl->handshake->pmslen, - ssl->handshake->premaster, - MBEDTLS_MPI_MAX_SIZE, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) @@ -3039,15 +3298,17 @@ ecdh_calc_secret: if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " - "SSL buffer too short" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity too long or SSL buffer too short" ) ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); } ssl->out_msg[i++] = (unsigned char)( n >> 8 ); ssl->out_msg[i++] = (unsigned char)( n ); - memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len ); + memcpy( ssl->out_msg + i, + ssl->conf->psk_identity, + ssl->conf->psk_identity_len ); i += ssl->conf->psk_identity_len; #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) @@ -3075,8 +3336,8 @@ ecdh_calc_secret: if( i + 2 + n > MBEDTLS_SSL_OUT_CONTENT_LEN ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" - " or SSL buffer too short" ) ); + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity or DHM size too long or SSL buffer too short" ) ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); } @@ -3123,7 +3384,8 @@ ecdh_calc_secret: if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, ciphersuite_info->key_exchange ) ) != 0 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_psk_derive_premaster", ret ); return( ret ); } } @@ -3332,8 +3594,9 @@ sign: * Until we encounter a server that does not, we will take this * shortcut. * - * Reason: Otherwise we should have running hashes for SHA512 and SHA224 - * in order to satisfy 'weird' needs from the server side. + * Reason: Otherwise we should have running hashes for SHA512 and + * SHA224 in order to satisfy 'weird' needs from the server + * side. */ if( ssl->transform_negotiate->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) @@ -3423,8 +3686,10 @@ static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } diff --git a/thirdparty/mbedtls/library/ssl_cookie.c b/thirdparty/mbedtls/library/ssl_cookie.c index 56e9bdd2bf..15a3173773 100644 --- a/thirdparty/mbedtls/library/ssl_cookie.c +++ b/thirdparty/mbedtls/library/ssl_cookie.c @@ -2,7 +2,13 @@ * DTLS cookie callbacks implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* @@ -133,8 +160,7 @@ static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, { unsigned char hmac_out[COOKIE_MD_OUTLEN]; - if( (size_t)( end - *p ) < COOKIE_HMAC_LEN ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN ); if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || @@ -164,8 +190,7 @@ int mbedtls_ssl_cookie_write( void *p_ctx, if( ctx == NULL || cli_id == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - if( (size_t)( end - *p ) < COOKIE_LEN ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN ); #if defined(MBEDTLS_HAVE_TIME) t = (unsigned long) mbedtls_time( NULL ); diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c index 5825970c43..2c31a8ac54 100644 --- a/thirdparty/mbedtls/library/ssl_srv.c +++ b/thirdparty/mbedtls/library/ssl_srv.c @@ -2,7 +2,13 @@ * SSLv3/TLSv1 server-side functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c index 8492c19a8c..4a091bb640 100644 --- a/thirdparty/mbedtls/library/ssl_ticket.c +++ b/thirdparty/mbedtls/library/ssl_ticket.c @@ -2,7 +2,13 @@ * TLS server tickets callbacks implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -35,6 +62,7 @@ #define mbedtls_free free #endif +#include "mbedtls/ssl_internal.h" #include "mbedtls/ssl_ticket.h" #include "mbedtls/platform_util.h" @@ -54,6 +82,19 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) #define MAX_KEY_BYTES 32 /* 256 bits */ +#define TICKET_KEY_NAME_BYTES 4 +#define TICKET_IV_BYTES 12 +#define TICKET_CRYPT_LEN_BYTES 2 +#define TICKET_AUTH_TAG_BYTES 16 + +#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES + \ + TICKET_AUTH_TAG_BYTES ) +#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES ) + /* * Generate/update a key */ @@ -278,6 +319,7 @@ static int ssl_load_session( mbedtls_ssl_session *session, * The key_name, iv, and length of encrypted_state are the additional * authenticated data. */ + int mbedtls_ssl_ticket_write( void *p_ticket, const mbedtls_ssl_session *session, unsigned char *start, @@ -289,9 +331,9 @@ int mbedtls_ssl_ticket_write( void *p_ticket, mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_key *key; unsigned char *key_name = start; - unsigned char *iv = start + 4; - unsigned char *state_len_bytes = iv + 12; - unsigned char *state = state_len_bytes + 2; + unsigned char *iv = start + TICKET_KEY_NAME_BYTES; + unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; + unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; unsigned char *tag; size_t clear_len, ciph_len; @@ -302,8 +344,7 @@ int mbedtls_ssl_ticket_write( void *p_ticket, /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, * in addition to session itself, that will be checked when writing it. */ - if( end - start < 4 + 12 + 2 + 16 ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN ); #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) @@ -317,9 +358,9 @@ int mbedtls_ssl_ticket_write( void *p_ticket, *ticket_lifetime = ctx->ticket_lifetime; - memcpy( key_name, key->name, 4 ); + memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES ); - if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 ) + if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 ) goto cleanup; /* Dump session state */ @@ -335,8 +376,11 @@ int mbedtls_ssl_ticket_write( void *p_ticket, /* Encrypt and authenticate */ tag = state + clear_len; if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, - iv, 12, key_name, 4 + 12 + 2, - state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 ) + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, state, &ciph_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) { goto cleanup; } @@ -346,7 +390,7 @@ int mbedtls_ssl_ticket_write( void *p_ticket, goto cleanup; } - *tlen = 4 + 12 + 2 + 16 + ciph_len; + *tlen = TICKET_MIN_LEN + ciph_len; cleanup: #if defined(MBEDTLS_THREADING_C) @@ -385,17 +429,16 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_key *key; unsigned char *key_name = buf; - unsigned char *iv = buf + 4; - unsigned char *enc_len_p = iv + 12; - unsigned char *ticket = enc_len_p + 2; + unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; + unsigned char *enc_len_p = iv + TICKET_IV_BYTES; + unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; unsigned char *tag; size_t enc_len, clear_len; if( ctx == NULL || ctx->f_rng == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* See mbedtls_ssl_ticket_write() */ - if( len < 4 + 12 + 2 + 16 ) + if( len < TICKET_MIN_LEN ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); #if defined(MBEDTLS_THREADING_C) @@ -409,7 +452,7 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; tag = ticket + enc_len; - if( len != 4 + 12 + 2 + enc_len + 16 ) + if( len != TICKET_MIN_LEN + enc_len ) { ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; goto cleanup; @@ -425,9 +468,13 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, } /* Decrypt and authenticate */ - if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12, - key_name, 4 + 12 + 2, ticket, enc_len, - ticket, &clear_len, tag, 16 ) ) != 0 ) + if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len, + ticket, &clear_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) { if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) ret = MBEDTLS_ERR_SSL_INVALID_MAC; diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c index cbec74fe8c..a40b46a1c0 100644 --- a/thirdparty/mbedtls/library/ssl_tls.c +++ b/thirdparty/mbedtls/library/ssl_tls.c @@ -2,7 +2,13 @@ * SSLv3/TLSv1 shared functions * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* @@ -2269,10 +2296,20 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen ); mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); - /* Call mbedtls_md_process at least once due to cache attacks - * that observe whether md_process() was called of not */ + /* Dummy calls to compression function. + * Call mbedtls_md_process at least once due to cache attacks + * that observe whether md_process() was called of not. + * Respect the usual start-(process|update)-finish sequence for + * the sake of hardware accelerators that might require it. */ + mbedtls_md_starts( &ssl->transform_in->md_ctx_dec ); for( j = 0; j < extra_run + 1; j++ ) mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); + { + /* The switch statement above already checks that we're using + * one of MD-5, SHA-1, SHA-256 or SHA-384. */ + unsigned char tmp[384 / 8]; + mbedtls_md_finish( &ssl->transform_in->md_ctx_dec, tmp ); + } mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); @@ -7589,7 +7626,9 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot cur_len = strlen( *p ); tot_len += cur_len; - if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) + if( ( cur_len == 0 ) || + ( cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN ) || + ( tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index 7c90c7c595..144fe5d46c 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -2,7 +2,13 @@ * Threading abstraction layer * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index 009516a6e3..a4beff35a9 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -2,7 +2,13 @@ * Portable interface to the CPU cycle counter * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/version.c b/thirdparty/mbedtls/library/version.c index fd96750885..bdba12f613 100644 --- a/thirdparty/mbedtls/library/version.c +++ b/thirdparty/mbedtls/library/version.c @@ -2,7 +2,13 @@ * Version information * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index 3b67b2be85..51662bfd21 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -2,7 +2,13 @@ * Version feature information * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ @@ -351,6 +378,9 @@ static const char *features[] = { #if defined(MBEDTLS_ECP_NIST_OPTIM) "MBEDTLS_ECP_NIST_OPTIM", #endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + "MBEDTLS_ECP_NO_INTERNAL_RNG", +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ #if defined(MBEDTLS_ECP_RESTARTABLE) "MBEDTLS_ECP_RESTARTABLE", #endif /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c index 4d25303206..63ceaf9f4d 100644 --- a/thirdparty/mbedtls/library/x509.c +++ b/thirdparty/mbedtls/library/x509.c @@ -2,7 +2,13 @@ * X.509 common functions for parsing and verification * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/x509_create.c b/thirdparty/mbedtls/library/x509_create.c index 546e8fa1a9..75de91f6c8 100644 --- a/thirdparty/mbedtls/library/x509_create.c +++ b/thirdparty/mbedtls/library/x509_create.c @@ -2,7 +2,13 @@ * X.509 base functions for creating certificates / CSRs * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/mbedtls/library/x509_crl.c b/thirdparty/mbedtls/library/x509_crl.c index 00f8545d7c..94c0c01afe 100644 --- a/thirdparty/mbedtls/library/x509_crl.c +++ b/thirdparty/mbedtls/library/x509_crl.c @@ -2,7 +2,13 @@ * X.509 Certidicate Revocation List (CRL) parsing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c index a3697f13f9..7d01585472 100644 --- a/thirdparty/mbedtls/library/x509_crt.c +++ b/thirdparty/mbedtls/library/x509_crt.c @@ -2,7 +2,13 @@ * X.509 certificate parsing and verification * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* @@ -527,6 +554,12 @@ static int x509_get_basic_constraints( unsigned char **p, return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer + * overflow, which is an undefined behavior. */ + if( *max_pathlen == INT_MAX ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*max_pathlen)++; return( 0 ); diff --git a/thirdparty/mbedtls/library/x509_csr.c b/thirdparty/mbedtls/library/x509_csr.c index c8c08c87b2..5045c10830 100644 --- a/thirdparty/mbedtls/library/x509_csr.c +++ b/thirdparty/mbedtls/library/x509_csr.c @@ -2,7 +2,13 @@ * X.509 Certificate Signing Request (CSR) parsing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/x509write_crt.c b/thirdparty/mbedtls/library/x509write_crt.c index 61d7ba44a0..0fc94fed2e 100644 --- a/thirdparty/mbedtls/library/x509write_crt.c +++ b/thirdparty/mbedtls/library/x509write_crt.c @@ -2,7 +2,13 @@ * X.509 certificate writing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/x509write_csr.c b/thirdparty/mbedtls/library/x509write_csr.c index 7406a97542..d1b0716c96 100644 --- a/thirdparty/mbedtls/library/x509write_csr.c +++ b/thirdparty/mbedtls/library/x509write_csr.c @@ -2,7 +2,13 @@ * X.509 Certificate Signing Request writing * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ /* diff --git a/thirdparty/mbedtls/library/xtea.c b/thirdparty/mbedtls/library/xtea.c index a33707bc17..26ec5de5a9 100644 --- a/thirdparty/mbedtls/library/xtea.c +++ b/thirdparty/mbedtls/library/xtea.c @@ -2,7 +2,13 @@ * An 32-bit implementation of the XTEA algorithm * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. @@ -16,6 +22,27 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/thirdparty/wslay/includes/wslay/wslayver.h b/thirdparty/wslay/includes/wslay/wslayver.h index 2c3e282e9d..28f2018039 100644 --- a/thirdparty/wslay/includes/wslay/wslayver.h +++ b/thirdparty/wslay/includes/wslay/wslayver.h @@ -26,6 +26,6 @@ #define WSLAYVER_H /* Version number of wslay release */ -#define WSLAY_VERSION "1.1.0" +#define WSLAY_VERSION "1.1.1" #endif /* WSLAYVER_H */ diff --git a/thirdparty/wslay/wslay_event.c b/thirdparty/wslay/wslay_event.c index 57415c51e0..140f7c01da 100644 --- a/thirdparty/wslay/wslay_event.c +++ b/thirdparty/wslay/wslay_event.c @@ -730,11 +730,11 @@ int wslay_event_recv(wslay_event_context_ptr ctx) return r; } } else if(ctx->imsg->opcode == WSLAY_PING) { - struct wslay_event_msg arg; - arg.opcode = WSLAY_PONG; - arg.msg = msg; - arg.msg_length = ctx->imsg->msg_length; - if((r = wslay_event_queue_msg(ctx, &arg)) && + struct wslay_event_msg pong_arg; + pong_arg.opcode = WSLAY_PONG; + pong_arg.msg = msg; + pong_arg.msg_length = ctx->imsg->msg_length; + if((r = wslay_event_queue_msg(ctx, &pong_arg)) && r != WSLAY_ERR_NO_MORE_MSG) { ctx->read_enabled = 0; free(msg); @@ -885,7 +885,7 @@ int wslay_event_send(wslay_event_context_ptr ctx) r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf), &ctx->omsg->source, &eof, ctx->user_data); - if(r == 0) { + if(r == 0 && eof == 0) { break; } else if(r < 0) { ctx->write_enabled = 0; |