diff options
43 files changed, 307 insertions, 154 deletions
@@ -118,6 +118,7 @@ Nathan Warden <nathan@nathanwarden.com> <nathanwardenlee@icloud.com> Nicholas Huelin <62965063+SirQuartz@users.noreply.github.com> Nils ANDRÉ-CHANG <nils@nilsand.re> Nils ANDRÉ-CHANG <nils@nilsand.re> <nils.andre.chang@gmail.com> +Nông Văn Tình <vannongtinh@gmail.com> Nuno Donato <nunodonato@gmail.com> <n.donato@estrelasustentavel.pt> ocean (they/them) <anvilfolk@gmail.com> Pawel Kowal <pkowal1982@gmail.com> diff --git a/AUTHORS.md b/AUTHORS.md index cf53f39cda..768eb4f904 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -31,6 +31,7 @@ name is available. Aaron Record (LightningAA) Adam Scott (adamscott) Alexander Holland (AlexHolly) + Alex Drozd (brno32) Alexey Khoroshavin (allkhor) Alfred Reinold Baudisch (alfredbaudisch) Alket Rexhepi (alketii) @@ -46,6 +47,7 @@ name is available. Aren Villanueva (kurikaesu) Ariel Manzur (punto-) AThousandShips + aXu-AP Bartłomiej T. Listwon (Listwon) Bastiaan Olij (BastiaanOlij) Ben Brookshire (sheepandshepherd) @@ -53,6 +55,7 @@ name is available. Bernhard Liebl (poke1024) Bhuvan Vemula (Bhu1-V) bitsawer + BlueCube3310 Błażej Szczygieł (zaps166) Bojidar Marinov (bojidar-bg) Brian Semrau (briansemrau) @@ -159,6 +162,7 @@ name is available. Lucien Menassol (Kanabenki) Lyuma Maganty Rushyendra (mrushyendra) + Malcolm Nixon (Malcolmnixon) Manuele Finocchiaro (m4nu3lf) Marcel Admiraal (madmiraal) Marcelo Fernandez (marcelofg55) @@ -191,6 +195,7 @@ name is available. Micky (Mickeon) Mikael Hermansson (mihe) MinusKube + MJacred Morris "Tabor" Arroad (mortarroad) mrezai Muhammad Huri (CakHuri) @@ -209,6 +214,7 @@ name is available. Omar El Sheikh (The-O-King) Ovnuniarchos Pascal Richter (ShyRed) + Patrick Dawson (pkdawson) Patrick Exner (FlameLizard) Patrick (firefly2442) Paul Batty (Paulb23) @@ -237,6 +243,7 @@ name is available. Ricardo Subtil (Ev1lbl0w) Riteo Siuga (Riteo) Roberto F. Arroyo (robfram) + Robert Yevdokimov (ryevdokimov) Robin Hübner (profan) romulox-x Rune Smith (rune-scape) @@ -245,6 +252,7 @@ name is available. Saniko (sanikoyes) santouits SaracenOne + Septian Ganendra S. K. (sepTN) Sergey Minakov (naithar) sersoong Shiqing (kawa-yoiko) @@ -252,6 +260,8 @@ name is available. Simon Wenner (swenner) smix8 snailrhymer + Sofox (TheSofox) + Stanislav Labzyuk (DarkMessiah) Stijn Hinlopen (hinlopen) stmSi Swarnim Arun (minraws) @@ -17,6 +17,7 @@ generous deed immortalized in the next stable release of Godot Engine. ## Platinum sponsors + Google Play <https://play.google.com> Heroic Labs <https://heroiclabs.com> Ramatak <https://ramatak.com> V-Sekai <https://github.com/V-Sekai> @@ -35,6 +36,7 @@ generous deed immortalized in the next stable release of Godot Engine. Chasing Carrots <https://www.chasing-carrots.com> Delton Ding Gamblify <https://www.gamblify.com> + Indoor Astronaut <https://indoorastronaut.ch> Null <https://null.com> Orbital Knight <https://www.orbitalknight.com> Playful Studios <https://playfulstudios.com> @@ -43,10 +45,11 @@ generous deed immortalized in the next stable release of Godot Engine. Sealow Sylv <https://rankith.itch.io/unnamed-space-idle-prototype> - And 5 anonymous donors + And 3 anonymous donors ## Titanium members + Adriaan de Jongh <https://adriaan.games/> Basically Games FDG Entertainment <https://www.fdg-entertainment.com/> Game Dev Artisan <https://gamedevartisan.com/> @@ -54,40 +57,41 @@ generous deed immortalized in the next stable release of Godot Engine. Isaiah Smith <https://www.isaiahsmith.dev/> katnamag <https://katnamag.com/> Kenney <https://kenney.nl/> + Life Art Studios <https://lifeartstudios.net/> Lucid Silence Games Matthew Campbell Maxim Karsten Midjiwan AB <https://polytopia.io/> PolyMars <https://polymars.dev/> Razenpok <https://www.youtube.com/watch?v=-QxI-RP6-HM> - RPG in a Box <https://www.rpginabox.com/> + Smirk Software <https://smirk.gg/> Sterling Long <https://www.sterlinglong.me/> Sunshower <https://github.com/Phanterm> TrampolineTales <https://trampolinetales.com/> Wilfred James <https://twitter.com/0430agi> - And 8 anonymous donors + 粟二华 (Su Erhua) + And 5 anonymous donors ## Platinum members AD Ford - Andy Touch BlockImperiumGames (BIG) - Christian Baune Christoph Woinke Christopher Shifflett Darrin Massena Druvsaft Edward Flick - F*ckedByUnity - Golden Skull Art HP van Braam + iCommitGames Jonah Stich Justin McGettigan Justo Delgado Baudí Marek Belski Matthew Ekenstedt + Memories in 8Bit Mike King Nassor Paulino da Silva + nate-wilkins Neal Gompa (Conan Kudo) Ronnie Cheng Ryan Heath @@ -99,57 +103,49 @@ generous deed immortalized in the next stable release of Godot Engine. Stephan Lanfermann TigerJ Tim Yuen + Tobias Holewa Violin Iliev Vladimír Chvátil - iCommitGames - nate-wilkins - And 18 anonymous donors + And 17 anonymous donors ## Gold members @reilaos + albinaask + alMoo Games + Alva Majo Antti Vesanen Artur Ilkaev - Asher Glick - Ashtreighlia - Atsui Ben Burbank Ben Rog-Wilhelm Benito Benjamin Sarsgard - Benjo Kho Bernd Barsuhn - Blake Farnsworth Brian Ernst Brian Levinsen Brut + Carlo del Mundo Chen-Pang He (jdh8) ClarkThyLord Cosmin Munteanu Coy Humphrey - Daniel James - David Chen Zhen - David Coles David Hubber David Snopek Dehyvis Coronel Dustuu Ed Morley ElektroFox - Enclusa Games + endaye Ends Eric Phy Faisal Al-Kubaisi (QatariGameDev) - FeralBytes - Frederick Ayala + getIntoGameDev GlassBrick Grau - Guangzhou Lingchan HTML5onMobilePLZ Hammster - Hendrik Mans Here's my 20 cents - Iggy Zuk + hiulit Illyan Jacob (HACKhalo2 Studios) Jam @@ -162,66 +158,48 @@ generous deed immortalized in the next stable release of Godot Engine. José Canepa João Pedro Braz KAR Games - Kamran Wali Karasu Studio - KekLuck - Kenneth Christensen + korinVR Kristian Kriehl Logan Apple Luca Junge Luca Vazzano LyaaaaaGames MHDante - Malcolm Nixon - Manuel Requena + Mara Huldra Mark Schramm Martin Agnar Dahl Martin Šenkeřík - Matheus Gritz + Matthew Hillier Megabit Interactive - Mennskr - Metanaut Modus Ponens - Niklas Wahrman + nezticle NotNet - Obelisk Island Studios Officine Pixel S.n.c. + ohanaya3 Oleksii Nosov Pav Soor - Piotr Siuszko RAWRLAB Games - RadenTheFolf + Rafa Laguna Request + re:thinc Robin Ward Saltlight Studio Samuel Judd Silverclad Studios - Sofox Space Kraken Studios Spoony Panda Sympa City + ThatGamer ThePolyglotProgrammer - Tim Nedvyga Tom Langwaldt Trevor Slocum - Vincent Foulon - Weasel Games - WuotanStudios.com - Zi - albinaask - endaye - getIntoGameDev - hiulit - korinVR - nezticle - ohanaya3 - re:thinc tukon + Weasel Games + Zhu Li zikes - 杨烈胜(zedrun) Alexander Erlemann - Alexandre VALIN Alex Khayrullin Algebrute Andriy @@ -237,13 +215,11 @@ generous deed immortalized in the next stable release of Godot Engine. Craig Swain CzechBlueBear Daniel Eichler - Daniel Reed Dennis Belfrage Emily A. Bellows Eric Brand Felix Winterhalter Fransiska - George Venizelos Harry Tumber Harvey Fong Horváth-Lázár Péter @@ -269,7 +245,6 @@ generous deed immortalized in the next stable release of Godot Engine. Michael Dürwald Michael Policastro n00sh - nate etan Nicolás Monner Sans Nikita Rotskov Nikola Whallon @@ -286,19 +261,14 @@ generous deed immortalized in the next stable release of Godot Engine. Ruzgud Ryan Breaker "Sage Automatic Systems, LLC" - Shishir Tandale - Song Junwoo spacechase0 sus - Talii Thomas Kurz Tobias Bocanegra - Tobias Raggl Torbulous toto bibi Valryia VoidPointer - whatever Yifan Lai zkip lan @@ -315,7 +285,6 @@ generous deed immortalized in the next stable release of Godot Engine. AJWolbers Aki Mimoto Alan Beauchamp - Alder Stefano Alejandro Saucedo AleMax Alex Clavelle @@ -323,15 +292,11 @@ generous deed immortalized in the next stable release of Godot Engine. alex raeside Andre Altmueller Andreas Østergaard Nielsen - Andrei Pufu - Andre Stackhouse Andrew - Andrew Groot andrew james morris Ano Nim Arch Toasty Arda Erol - Arthur Brainville Arturo Rosales Ash K Aubrey Falconer @@ -347,17 +312,18 @@ generous deed immortalized in the next stable release of Godot Engine. Bread Brian Ford Caleb Makela - Caliburn Cameron Meyer Carlos Rios Carl van der Geest Cerno_b + ChainZ Checkpoint Charlie chendrak Chris Cavalluzzi Chris Jagusch Chris Lee Christian Mauduit + Christian Ringshofer Christoph Czurda Christophe Gagnier Ciyvius @@ -368,7 +334,6 @@ generous deed immortalized in the next stable release of Godot Engine. cynwav Dakota Watkins Daniele Tolomelli - Daniel Hoffmann Daniel Ramos Daren Scot Wilson Dave Jansen @@ -387,18 +352,16 @@ generous deed immortalized in the next stable release of Godot Engine. Edward Swartz Egon Elbre Elijah Anderson - Emerson MX - Ephemeral Eric Persson Eric Stokes Eric Williams Erkki Seppälä Ewan Holmes Felix Adam - Fer DC Frank Frying☆Pan Game Endeavor + gamerminstrel Garrett Steffen Gary Thomas gebba @@ -408,7 +371,6 @@ generous deed immortalized in the next stable release of Godot Engine. Grominet Guldoman Guo Hongci - Hans Jorgensen Haplo Helge Maus Heribert Hirth @@ -419,21 +381,19 @@ generous deed immortalized in the next stable release of Godot Engine. Jacob Wallace Jako Danar James Gary + James Hulsizer Jamie Massey JARKKO PARVIAINEN Jason Evans - Jason Uechi Jeff Hungerford Jeffrey Berube Jennifer Graves Joakim Askenbäck - João Pedro Braz John Bruce Jonas Jonas Arndt Jonas Yamazaki Jonathan Bieber - Jonathan Ellis Jon Sully Joseph Catrambone Josh Taylor @@ -443,10 +403,8 @@ generous deed immortalized in the next stable release of Godot Engine. Juan Uys Jueast Julian le Roux - Justin Justin Spedding Kalydi Balázs - Katsuomi Kobayashi Keedong Park Keegan Scott Keith Bradner @@ -455,8 +413,8 @@ generous deed immortalized in the next stable release of Godot Engine. Kodera Software KsyTek Games Kyle Burnett + Kyle Haltermann Kyle Jacobs - Lasse le Dous Leland Vakarian Levi Berciu Linus Lind Lundgren @@ -468,9 +426,9 @@ generous deed immortalized in the next stable release of Godot Engine. Major Haul Malcolm Manuele Finocchiaro - Mara Huldra Marcos Heitor Carvalho Markie Music + Mark Tyler Markus Michael Egger Markus Strompen Martin Holas @@ -483,7 +441,6 @@ generous deed immortalized in the next stable release of Godot Engine. Maverick Maxime Blade Maxwell - McStuffings Melissa Mears Metal Demon 2000 Michael Morrison @@ -491,7 +448,6 @@ generous deed immortalized in the next stable release of Godot Engine. Mikael Nordenberg Mikayla Mike Copley - Mitchell J. Wagner Molly Jameson MoltenGears Moritz Weissenberger @@ -499,7 +455,6 @@ generous deed immortalized in the next stable release of Godot Engine. Mrjemandem naonya3 Nathaniel - neguse neighty Neil Blakey-Milner Neofytos Chimonas @@ -510,18 +465,15 @@ generous deed immortalized in the next stable release of Godot Engine. Nik Rudenko Noel Billig Olexa Tourko - oscar1000108 Oscar Domingo ozrk Parth Patel Patrick Horn - Patrick Indermühle Patrickm Patrick Nafarrete Paul Black Paul Gieske Paul Mozet - Paweł Łyczkowski Pete Philip Ludington (MrPhil) Phoenix Jauregui @@ -542,17 +494,14 @@ generous deed immortalized in the next stable release of Godot Engine. Riley RobotCritter Rob Ruana - Rodrigo Loli Roka Roland Rząsa Russ Ryan Groom Sammy Fischer Sebastian Michailidis - Sekuta SeongWan Kim Sessamekesh - SeungJong k Shane Lillie Shane Spoor Shaun Kohanowski @@ -571,6 +520,7 @@ generous deed immortalized in the next stable release of Godot Engine. Stephen Rice Stephen Schlie Sung soo Choi + Sven Walter SxP tadashi endo Tarch @@ -580,12 +530,12 @@ generous deed immortalized in the next stable release of Godot Engine. Thomas Bechtold Thomas Pickett Tim Drumheller - Tim Gleason Tim Klein Timothy B. MacDonald Tim Raveling Tim Riley Tom Webster + Trent Skinner Turgut Temucin Tyler Stafos Tyler Stepke @@ -593,20 +543,16 @@ generous deed immortalized in the next stable release of Godot Engine. Uther Vaughan Ling vgmoose - Vincent Barkmann Vulinux Wapiti . - wasitworthitdev Wiley Thompson - William Bodin - William Edwards Xatonym Yan Shi Zekim ケルベロス 貴宏 小松 - And 241 anonymous donors + And 196 anonymous donors ## Silver and bronze donors diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index e3a7eda563..2a54ae0527 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -125,6 +125,7 @@ </member> <member name="billboard_mode" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="BaseMaterial3D.BillboardMode" default="0"> Controls how the object faces the camera. See [enum BillboardMode]. + [b]Note:[/b] When billboarding is enabled and the material also casts shadows, billboards will face [b]the[/b] camera in the scene when rendering shadows. In scenes with multiple cameras, the intended shadow cannot be determined and this will result in undefined behavior. See [url=https://github.com/godotengine/godot/pull/72638]GitHub Pull Request #72638[/url] for details. [b]Note:[/b] Billboard mode is not suitable for VR because the left-right vector of the camera is not horizontal when the screen is attached to your head instead of on the table. See [url=https://github.com/godotengine/godot/issues/41567]GitHub issue #41567[/url] for details. </member> <member name="blend_mode" type="int" setter="set_blend_mode" getter="get_blend_mode" enum="BaseMaterial3D.BlendMode" default="0"> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 86b4571782..b23d605d9e 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -898,6 +898,9 @@ If [code]true[/code], text resources are converted to a binary format on export. This decreases file sizes and speeds up loading slightly. [b]Note:[/b] If [member editor/export/convert_text_resources_to_binary] is [code]true[/code], [method @GDScript.load] will not be able to return the converted files in an exported project. Some file paths within the exported PCK will also change, such as [code]project.godot[/code] becoming [code]project.binary[/code]. If you rely on run-time loading of files present within the PCK, set [member editor/export/convert_text_resources_to_binary] to [code]false[/code]. </member> + <member name="editor/import/atlas_max_width" type="int" setter="" getter="" default="2048"> + The maximum width to use when importing textures as an atlas. The value will be rounded to the nearest power of two when used. Use this to prevent imported textures from growing too large in the other direction. + </member> <member name="editor/import/reimport_missing_imported_files" type="bool" setter="" getter="" default="true"> </member> <member name="editor/import/use_multiple_threads" type="bool" setter="" getter="" default="true"> diff --git a/doc/classes/SpriteBase3D.xml b/doc/classes/SpriteBase3D.xml index a87608bb72..601340ca91 100644 --- a/doc/classes/SpriteBase3D.xml +++ b/doc/classes/SpriteBase3D.xml @@ -58,6 +58,7 @@ </member> <member name="billboard" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="BaseMaterial3D.BillboardMode" default="0"> The billboard mode to use for the sprite. See [enum BaseMaterial3D.BillboardMode] for possible values. + [b]Note:[/b] When billboarding is enabled and the material also casts shadows, billboards will face [b]the[/b] camera in the scene when rendering shadows. In scenes with multiple cameras, the intended shadow cannot be determined and this will result in undefined behavior. See [url=https://github.com/godotengine/godot/pull/72638]GitHub Pull Request #72638[/url] for details. </member> <member name="centered" type="bool" setter="set_centered" getter="is_centered" default="true"> If [code]true[/code], texture will be centered. diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp index 0db07177a5..8d1045b2b3 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.cpp +++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp @@ -1585,6 +1585,8 @@ RDD::TextureID RenderingDeviceDriverD3D12::texture_create_shared_from_slice(Text uav_desc.Texture2DArray.FirstArraySlice = p_layer; uav_desc.Texture2DArray.ArraySize = p_layers; } break; + default: + break; } // Bookkeep. @@ -2253,7 +2255,11 @@ Error RenderingDeviceDriverD3D12::swap_chain_resize(CommandQueueID p_cmd_queue, texture_info.owner_info.states.subresource_states.push_back(D3D12_RESOURCE_STATE_PRESENT); texture_info.states_ptr = &texture_info.owner_info.states; texture_info.format = swap_chain->data_format; +#if defined(_MSC_VER) || !defined(_WIN32) texture_info.desc = CD3DX12_RESOURCE_DESC(render_target->GetDesc()); +#else + render_target->GetDesc(&texture_info.desc); +#endif texture_info.layers = 1; texture_info.mipmaps = 1; texture_info.resource = render_target; @@ -2520,8 +2526,6 @@ dxil_validator *RenderingDeviceDriverD3D12::_get_dxil_validator_for_current_thre #endif dxil_validator *dxil_validator = dxil_create_validator(nullptr); - CRASH_COND(!dxil_validator); - dxil_validators.insert(thread_idx, dxil_validator); return dxil_validator; } @@ -2658,6 +2662,14 @@ bool RenderingDeviceDriverD3D12::_shader_apply_specialization_constants( bool RenderingDeviceDriverD3D12::_shader_sign_dxil_bytecode(ShaderStage p_stage, Vector<uint8_t> &r_dxil_blob) { dxil_validator *validator = _get_dxil_validator_for_current_thread(); + if (!validator) { + if (is_in_developer_mode()) { + return true; + } else { + OS::get_singleton()->alert("Shader validation failed: DXIL.dll was not found, and developer mode is disabled.\n\nClick OK to exit."); + CRASH_NOW(); + } + } char *err = nullptr; bool res = dxil_validate_module(validator, r_dxil_blob.ptrw(), r_dxil_blob.size(), &err); @@ -2673,7 +2685,7 @@ bool RenderingDeviceDriverD3D12::_shader_sign_dxil_bytecode(ShaderStage p_stage, } String RenderingDeviceDriverD3D12::shader_get_binary_cache_key() { - return "D3D12-SV" + uitos(ShaderBinary::VERSION) + "-" + itos(shader_capabilities.shader_model); + return "D3D12-SV" + uitos(ShaderBinary::VERSION) + "-" + itos(shader_capabilities.shader_model) + (is_in_developer_mode() ? "dev" : ""); } Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(VectorView<ShaderStageSPIRVData> p_spirv, const String &p_shader_name) { @@ -2944,7 +2956,10 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec nir_to_dxil_options nir_to_dxil_options = {}; nir_to_dxil_options.environment = DXIL_ENVIRONMENT_VULKAN; nir_to_dxil_options.shader_model_max = shader_model_d3d_to_dxil(shader_capabilities.shader_model); - nir_to_dxil_options.validator_version_max = dxil_get_validator_version(_get_dxil_validator_for_current_thread()); + dxil_validator *validator = _get_dxil_validator_for_current_thread(); + if (validator) { + nir_to_dxil_options.validator_version_max = dxil_get_validator_version(validator); + } nir_to_dxil_options.godot_nir_callbacks = &godot_nir_callbacks; dxil_logger logger = {}; @@ -5652,7 +5667,7 @@ void RenderingDeviceDriverD3D12::begin_segment(uint32_t p_frame_index, uint32_t frames[frame_idx].desc_heap_walkers.aux.rewind(); frames[frame_idx].desc_heap_walkers.rtv.rewind(); frames[frame_idx].desc_heaps_exhausted_reported = {}; - frames[frame_idx].null_rtv_handle = {}; + frames[frame_idx].null_rtv_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE{}; frames[frame_idx].segment_serial = segment_serial; segment_begun = true; @@ -5878,15 +5893,42 @@ RenderingDeviceDriverD3D12::~RenderingDeviceDriverD3D12() { { MutexLock lock(dxil_mutex); for (const KeyValue<int, dxil_validator *> &E : dxil_validators) { - dxil_destroy_validator(E.value); + if (E.value) { + dxil_destroy_validator(E.value); + } } } glsl_type_singleton_decref(); } +bool RenderingDeviceDriverD3D12::is_in_developer_mode() { + HKEY hkey = NULL; + LSTATUS result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock", 0, KEY_READ, &hkey); + if (result != ERROR_SUCCESS) { + return false; + } + + DWORD value = 0; + DWORD dword_size = sizeof(DWORD); + result = RegQueryValueExW(hkey, L"AllowDevelopmentWithoutDevLicense", nullptr, nullptr, (PBYTE)&value, &dword_size); + RegCloseKey(hkey); + + if (result != ERROR_SUCCESS) { + return false; + } + + return (value != 0); +} + Error RenderingDeviceDriverD3D12::_initialize_device() { HRESULT res; + + if (is_in_developer_mode()) { + UUID experimental_features[] = { D3D12ExperimentalShaderModels }; + D3D12EnableExperimentalFeatures(1, experimental_features, nullptr, nullptr); + } + ID3D12DeviceFactory *device_factory = context_driver->device_factory_get(); if (device_factory != nullptr) { res = device_factory->CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf())); diff --git a/drivers/d3d12/rendering_device_driver_d3d12.h b/drivers/d3d12/rendering_device_driver_d3d12.h index 5fe5aff6cf..595ee30966 100644 --- a/drivers/d3d12/rendering_device_driver_d3d12.h +++ b/drivers/d3d12/rendering_device_driver_d3d12.h @@ -977,6 +977,8 @@ public: virtual String get_pipeline_cache_uuid() const override final; virtual const Capabilities &get_capabilities() const override final; + static bool is_in_developer_mode(); + private: /*********************/ /**** BOOKKEEPING ****/ diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index f0a6397041..6cca1fef7e 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1555,6 +1555,7 @@ void RasterizerSceneGLES3::_setup_environment(const RenderDataGLES3 *p_render_da GLES3::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); GLES3::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); GLES3::MaterialStorage::store_transform(p_render_data->inv_cam_transform, scene_state.ubo.view_matrix); + GLES3::MaterialStorage::store_transform(p_render_data->main_cam_transform, scene_state.ubo.main_cam_inv_view_matrix); scene_state.ubo.camera_visible_layers = p_render_data->camera_visible_layers; if (p_render_data->view_count > 1) { @@ -2095,20 +2096,20 @@ void RasterizerSceneGLES3::_render_shadows(const RenderDataGLES3 *p_render_data, // Render cubemap shadows. for (const int &index : cube_shadows) { - _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->render_info, p_viewport_size); + _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->render_info, p_viewport_size, p_render_data->cam_transform); } // Render directional shadows. for (uint32_t i = 0; i < directional_shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[directional_shadows[i]].pass, p_render_data->render_shadows[directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->render_info, p_viewport_size); + _render_shadow_pass(p_render_data->render_shadows[directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[directional_shadows[i]].pass, p_render_data->render_shadows[directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->render_info, p_viewport_size, p_render_data->cam_transform); } // Render positional shadows (Spotlight and Omnilight with dual-paraboloid). for (uint32_t i = 0; i < shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[shadows[i]].pass, p_render_data->render_shadows[shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->render_info, p_viewport_size); + _render_shadow_pass(p_render_data->render_shadows[shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[shadows[i]].pass, p_render_data->render_shadows[shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->render_info, p_viewport_size, p_render_data->cam_transform); } } } -void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size) { +void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton(); ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); @@ -2242,6 +2243,7 @@ void RasterizerSceneGLES3::_render_shadow_pass(RID p_light, RID p_shadow_atlas, render_data.z_far = zfar; // Only used by OmniLights. render_data.z_near = 0.0; render_data.lod_distance_multiplier = p_lod_distance_multiplier; + render_data.main_cam_transform = p_main_cam_transform; render_data.instances = &p_instances; render_data.render_info = p_render_info; @@ -2330,6 +2332,7 @@ void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_ render_data.cam_projection = p_camera_data->main_projection; render_data.cam_orthogonal = p_camera_data->is_orthogonal; render_data.camera_visible_layers = p_camera_data->visible_layers; + render_data.main_cam_transform = p_camera_data->main_transform; render_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { @@ -3448,6 +3451,7 @@ void RasterizerSceneGLES3::render_particle_collider_heightfield(RID p_collider, render_data.cam_orthogonal = true; render_data.z_near = 0.0; render_data.z_far = cm.get_z_far(); + render_data.main_cam_transform = cam_xform; render_data.instances = &p_instances; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index efe614f692..7880591dcb 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -98,6 +98,9 @@ struct RenderDataGLES3 { bool cam_orthogonal = false; uint32_t camera_visible_layers = 0xFFFFFFFF; + // For billboards to cast correct shadows. + Transform3D main_cam_transform; + // For stereo rendering uint32_t view_count = 1; Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; @@ -370,6 +373,8 @@ private: float inv_view_matrix[16]; float view_matrix[16]; + float main_cam_inv_view_matrix[16]; + float viewport_size[2]; float screen_pixel_size[2]; @@ -538,7 +543,7 @@ private: void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows, float p_shadow_bias = 0.0); void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false); void _render_shadows(const RenderDataGLES3 *p_render_data, const Size2i &p_viewport_size = Size2i(1, 1)); - void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1)); + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D()); void _render_post_processing(const RenderDataGLES3 *p_render_data); template <PassMode p_pass_mode> diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 9e2c8a4452..ffdac85c1e 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -155,6 +155,9 @@ layout(std140) uniform SceneData { // ubo:2 highp mat4 inv_view_matrix; highp mat4 view_matrix; + // Used for billboards to cast correct shadows. + highp mat4 main_cam_inv_view_matrix; + vec2 viewport_size; vec2 screen_pixel_size; @@ -637,6 +640,9 @@ layout(std140) uniform SceneData { // ubo:2 highp mat4 inv_view_matrix; highp mat4 view_matrix; + // Used for billboards to cast correct shadows. + highp mat4 main_cam_inv_view_matrix; + vec2 viewport_size; vec2 screen_pixel_size; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index 80a6795ffe..5600449d00 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1209,6 +1209,7 @@ MaterialStorage::MaterialStorage() { actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; + actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix"; actions.renames["VERTEX"] = "vertex"; actions.renames["NORMAL"] = "normal"; diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp index 163ac4152c..aae06505cd 100644 --- a/drivers/windows/file_access_windows.cpp +++ b/drivers/windows/file_access_windows.cpp @@ -60,7 +60,12 @@ void FileAccessWindows::check_errors() const { bool FileAccessWindows::is_path_invalid(const String &p_path) { // Check for invalid operating system file. - String fname = p_path.get_file().get_basename().to_lower(); + String fname = p_path.get_file().to_lower(); + + int dot = fname.find("."); + if (dot != -1) { + fname = fname.substr(0, dot); + } return invalid_files.has(fname); } diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 7c269bd6ed..34ca653ff7 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -1548,7 +1548,8 @@ void AnimationBezierTrackEdit::_zoom_callback(float p_zoom_factor, Vector2 p_ori // Alternate zoom (doesn't affect timeline). timeline_v_zoom = CLAMP(timeline_v_zoom * p_zoom_factor, 0.000001, 100000); } else { - timeline->_zoom_callback(p_zoom_factor, p_origin, p_event); + float zoom_factor = p_zoom_factor > 1.0 ? AnimationTimelineEdit::SCROLL_ZOOM_FACTOR_IN : AnimationTimelineEdit::SCROLL_ZOOM_FACTOR_OUT; + timeline->_zoom_callback(zoom_factor, p_origin, p_event); } timeline_v_scroll = timeline_v_scroll + (p_origin.y - get_size().y / 2.0) * (timeline_v_zoom - v_zoom_orig); queue_redraw(); @@ -1823,7 +1824,6 @@ void AnimationBezierTrackEdit::_bind_methods() { AnimationBezierTrackEdit::AnimationBezierTrackEdit() { panner.instantiate(); panner->set_callbacks(callable_mp(this, &AnimationBezierTrackEdit::_pan_callback), callable_mp(this, &AnimationBezierTrackEdit::_zoom_callback)); - panner->set_scroll_zoom_factor(AnimationTimelineEdit::SCROLL_ZOOM_FACTOR); play_position = memnew(Control); play_position->set_mouse_filter(MOUSE_FILTER_PASS); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 713c21fc08..8b59abc713 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1868,7 +1868,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() { len_hb->hide(); panner.instantiate(); - panner->set_scroll_zoom_factor(SCROLL_ZOOM_FACTOR); + panner->set_scroll_zoom_factor(SCROLL_ZOOM_FACTOR_IN); panner->set_callbacks(callable_mp(this, &AnimationTimelineEdit::_pan_callback), callable_mp(this, &AnimationTimelineEdit::_zoom_callback)); panner->set_pan_axis(ViewPanner::PAN_AXIS_HORIZONTAL); @@ -6837,7 +6837,7 @@ AnimationTrackEditor::AnimationTrackEditor() { timeline->connect("length_changed", callable_mp(this, &AnimationTrackEditor::_update_length)); panner.instantiate(); - panner->set_scroll_zoom_factor(AnimationTimelineEdit::SCROLL_ZOOM_FACTOR); + panner->set_scroll_zoom_factor(AnimationTimelineEdit::SCROLL_ZOOM_FACTOR_IN); panner->set_callbacks(callable_mp(this, &AnimationTrackEditor::_pan_callback), callable_mp(this, &AnimationTrackEditor::_zoom_callback)); scroll = memnew(ScrollContainer); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 6d037bf5f9..bb84577ba3 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -134,7 +134,8 @@ class AnimationTimelineEdit : public Range { friend class AnimationBezierTrackEdit; friend class AnimationTrackEditor; - static constexpr float SCROLL_ZOOM_FACTOR = 1.02f; // Zoom factor per mouse scroll in the animation editor. The closer to 1.0, the finer the control. + static constexpr float SCROLL_ZOOM_FACTOR_IN = 1.02f; // Zoom factor per mouse scroll in the animation editor when zooming in. The closer to 1.0, the finer the control. + static constexpr float SCROLL_ZOOM_FACTOR_OUT = 0.98f; // Zoom factor when zooming out. Similar to SCROLL_ZOOM_FACTOR_IN but less than 1.0. Ref<Animation> animation; bool read_only = false; diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 00bf4b00b5..7f15eca11d 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -2720,6 +2720,10 @@ String EditorHelpBit::get_class_description(const StringName &p_class_name) cons } String EditorHelpBit::get_property_description(const StringName &p_class_name, const StringName &p_property_name) const { + if (!custom_description.is_empty()) { + return custom_description; + } + if (doc_property_cache.has(p_class_name) && doc_property_cache[p_class_name].has(p_property_name)) { return doc_property_cache[p_class_name][p_property_name]; } @@ -2975,8 +2979,9 @@ void EditorHelpTooltip::parse_tooltip(const String &p_text) { set_text(formatted_text); } -EditorHelpTooltip::EditorHelpTooltip(const String &p_text) { +EditorHelpTooltip::EditorHelpTooltip(const String &p_text, const String &p_custom_description) { tooltip_text = p_text; + custom_description = p_custom_description; get_rich_text()->set_custom_minimum_size(Size2(360 * EDSCALE, 0)); } diff --git a/editor/editor_help.h b/editor/editor_help.h index e788350e76..49d13c5522 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -265,6 +265,8 @@ class EditorHelpBit : public MarginContainer { String text; protected: + String custom_description; + static void _bind_methods(); void _notification(int p_what); @@ -292,7 +294,7 @@ protected: public: void parse_tooltip(const String &p_text); - EditorHelpTooltip(const String &p_text = String()); + EditorHelpTooltip(const String &p_text = String(), const String &p_custom_description = String()); }; #endif // EDITOR_HELP_H diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 6633121737..0f7a121a02 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -998,7 +998,13 @@ Control *EditorProperty::make_custom_tooltip(const String &p_text) const { EditorHelpBit *tooltip = nullptr; if (has_doc_tooltip) { - tooltip = memnew(EditorHelpTooltip(p_text)); + String custom_description; + + const EditorInspector *inspector = get_parent_inspector(); + if (inspector) { + custom_description = inspector->get_custom_property_description(p_text); + } + tooltip = memnew(EditorHelpTooltip(p_text, custom_description)); } if (object->has_method("_get_property_warning")) { @@ -4180,6 +4186,19 @@ String EditorInspector::get_property_prefix() const { return property_prefix; } +void EditorInspector::add_custom_property_description(const String &p_class, const String &p_property, const String &p_description) { + const String key = vformat("property|%s|%s|", p_class, p_property); + custom_property_descriptions[key] = p_description; +} + +String EditorInspector::get_custom_property_description(const String &p_property) const { + HashMap<String, String>::ConstIterator E = custom_property_descriptions.find(p_property); + if (E) { + return E->value; + } + return ""; +} + void EditorInspector::set_object_class(const String &p_class) { object_class = p_class; } diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index d8b3e32d7d..2066002a03 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -516,6 +516,7 @@ class EditorInspector : public ScrollContainer { HashMap<StringName, HashMap<StringName, String>> doc_path_cache; HashSet<StringName> restart_request_props; + HashMap<String, String> custom_property_descriptions; HashMap<ObjectID, int> scroll_cache; @@ -624,6 +625,9 @@ public: void set_property_prefix(const String &p_prefix); String get_property_prefix() const; + void add_custom_property_description(const String &p_class, const String &p_property, const String &p_description); + String get_custom_property_description(const String &p_property) const; + void set_object_class(const String &p_class); String get_object_class() const; diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index 9edf468ec6..d6ce39f6a6 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -31,6 +31,7 @@ #include "resource_importer_texture_atlas.h" #include "atlas_import_failed.xpm" +#include "core/config/project_settings.h" #include "core/io/file_access.h" #include "core/io/image_loader.h" #include "core/io/resource_saver.h" @@ -276,9 +277,15 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file idx++; } + const int max_width = (int)GLOBAL_GET("editor/import/atlas_max_width"); + //pack the charts int atlas_width, atlas_height; - EditorAtlasPacker::chart_pack(charts, atlas_width, atlas_height); + EditorAtlasPacker::chart_pack(charts, atlas_width, atlas_height, max_width); + + if (atlas_height > max_width * 2) { + WARN_PRINT(vformat(TTR("%s: Atlas texture significantly larger on one axis (%d), consider changing the `editor/import/atlas_max_width` Project Setting to allow a wider texture, making the result more even in size."), p_group_file, atlas_height)); + } //blit the atlas Ref<Image> new_atlas = Image::create_empty(atlas_width, atlas_height, false, Image::FORMAT_RGBA8); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index c48cbd8c20..9baf0c60dd 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -500,11 +500,14 @@ void ScriptTextEditor::_validate_script() { safe_lines.clear(); if (!script->get_language()->validate(text, script->get_path(), &fnc, &errors, &warnings, &safe_lines)) { - for (List<ScriptLanguage::ScriptError>::Element *E = errors.front(); E; E = E->next()) { + List<ScriptLanguage::ScriptError>::Element *E = errors.front(); + while (E) { + List<ScriptLanguage::ScriptError>::Element *next_E = E->next(); if ((E->get().path.is_empty() && !script->get_path().is_empty()) || E->get().path != script->get_path()) { depended_errors[E->get().path].push_back(E->get()); E->erase(); } + E = next_E; } if (errors.size() > 0) { diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index e3710adc83..7efa978a78 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -2406,7 +2406,36 @@ void TileSetAtlasSourceEditor::_auto_remove_tiles() { void TileSetAtlasSourceEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_READY: { + atlas_source_inspector->edit(atlas_source_proxy_object); + atlas_source_inspector->add_custom_property_description("TileSetAtlasSourceProxyObject", "id", TTR("The tile's unique identifier within this TileSet. Each tile stores its source ID, so changing one may make tiles invalid.")); + atlas_source_inspector->add_custom_property_description("TileSetAtlasSourceProxyObject", "name", TTR("The human-readable name for the atlas. Use a descriptive name here for organizational purposes (such as \"terrain\", \"decoration\", etc.).")); + atlas_source_inspector->add_custom_property_description("TileSetAtlasSourceProxyObject", "texture", TTR("The image from which the tiles will be created.")); + atlas_source_inspector->add_custom_property_description("TileSetAtlasSourceProxyObject", "margins", TTR("The margins on the image's edges that should not be selectable as tiles (in pixels). Increasing this can be useful if you download a tilesheet image that has margins on the edges (e.g. for attribution).")); + atlas_source_inspector->add_custom_property_description("TileSetAtlasSourceProxyObject", "separation", TTR("The separation between each tile on the atlas in pixels. Increasing this can be useful if the tilesheet image you're using contains guides (such as outlines between every tile).")); + atlas_source_inspector->add_custom_property_description("TileSetAtlasSourceProxyObject", "texture_region_size", TTR("The size of each tile on the atlas in pixels. In most cases, this should match the tile size defined in the TileMap property (although this is not strictly necessary).")); + atlas_source_inspector->add_custom_property_description("TileSetAtlasSourceProxyObject", "use_texture_padding", TTR("If checked, adds a 1-pixel transparent edge around each tile to prevent texture bleeding when filtering is enabled. It's recommended to leave this enabled unless you're running into rendering issues due to texture padding.")); + + tile_inspector->edit(tile_proxy_object); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "atlas_coords", TTR("The position of the tile's top-left corner in the atlas. The position and size must be within the atlas and can't overlap another tile.\nEach painted tile has associated atlas coords, so changing this property may cause your TileMaps to not display properly.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "size_in_atlas", TTR("The unit size of the tile.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "animation_columns", TTR("Number of columns for the animation grid. If number of columns is lower than number of frames, the animation will automatically adjust row count.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "animation_separation", TTR("The space (in tiles) between each frame of the animation.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "animation_speed", TTR("Animation speed in frames per second.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "animation_mode", TTR("Determines how animation will start. In \"Default\" mode all tiles start animating at the same frame. In \"Random Start Times\" mode, each tile starts animation with a random offset.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "flip_h", TTR("If [code]true[/code], the tile is horizontally flipped.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "flip_v", TTR("If [code]true[/code], the tile is vertically flipped.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "transpose", TTR("If [code]true[/code], the tile is rotated 90 degrees [i]counter-clockwise[/i] and then flipped vertically. In practice, this means that to rotate a tile by 90 degrees clockwise without flipping it, you should enable [b]Flip H[/b] and [b]Transpose[/b]. To rotate a tile by 180 degrees clockwise, enable [b]Flip H[/b] and [b]Flip V[/b]. To rotate a tile by 270 degrees clockwise, enable [b]Flip V[/b] and [b]Transpose[/b].")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "texture_origin", TTR("The origin to use for drawing the tile. This can be used to visually offset the tile compared to the base tile.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "modulate", TTR("The color multiplier to use when rendering the tile.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "material", TTR("The material to use for this tile. This can be used to apply a different blend mode or custom shaders to a single tile.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "z_index", TTR("The sorting order for this tile. Higher values will make the tile render in front of others on the same layer. The index is relative to the TileMap's own Z index.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "y_sort_origin", TTR("The vertical offset to use for tile sorting based on its Y coordinate (in pixels). This allows using layers as if they were on different height for top-down games. Adjusting this can help alleviate issues with sorting certain tiles. Only effective if Y Sort Enabled is true on the TileMap layer the tile is placed on.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "terrain_set", TTR("The index of the terrain set this tile belongs to. [code]-1[/code] means it will not be used in terrains.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "terrain", TTR("The index of the terrain inside the terrain set this tile belongs to. [code]-1[/code] means it will not be used in terrains.")); + tile_inspector->add_custom_property_description("AtlasTileProxyObject", "probability", TTR("The relative probability of this tile appearing when painting with \"Place Random Tile\" enabled.")); + } break; + case NOTIFICATION_THEME_CHANGED: { tool_setup_atlas_source_button->set_icon(get_editor_theme_icon(SNAME("Tools"))); tool_select_button->set_icon(get_editor_theme_icon(SNAME("ToolSelect"))); @@ -2526,7 +2555,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_inspector = memnew(EditorInspector); tile_inspector->set_v_size_flags(SIZE_EXPAND_FILL); tile_inspector->set_show_categories(true); - tile_inspector->edit(tile_proxy_object); + tile_inspector->set_use_doc_hints(true); tile_inspector->set_use_folding(true); tile_inspector->connect("property_selected", callable_mp(this, &TileSetAtlasSourceEditor::_inspector_property_selected)); middle_vbox_container->add_child(tile_inspector); @@ -2580,8 +2609,8 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { atlas_source_inspector = memnew(EditorInspector); atlas_source_inspector->set_v_size_flags(SIZE_EXPAND_FILL); atlas_source_inspector->set_show_categories(true); + atlas_source_inspector->set_use_doc_hints(true); atlas_source_inspector->add_inspector_plugin(memnew(TileSourceInspectorPlugin)); - atlas_source_inspector->edit(atlas_source_proxy_object); middle_vbox_container->add_child(atlas_source_inspector); // -- Right side -- diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index c43995d167..bb950dbf63 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -988,7 +988,7 @@ void TileSourceInspectorPlugin::_show_id_edit_dialog(Object *p_for_source) { void TileSourceInspectorPlugin::_confirm_change_id() { edited_source->set("id", id_input->get_value()); - id_label->set_text(vformat(TTR("ID: %d"), edited_source->get("id"))); // Use get(), because the provided ID might've been invalid. + id_label->set_text(itos(edited_source->get("id"))); // Use get(), because the provided ID might've been invalid. } bool TileSourceInspectorPlugin::can_handle(Object *p_object) { @@ -1002,17 +1002,22 @@ bool TileSourceInspectorPlugin::parse_property(Object *p_object, const Variant:: return true; } + EditorProperty *ep = memnew(EditorProperty); + HBoxContainer *hbox = memnew(HBoxContainer); hbox->set_alignment(BoxContainer::ALIGNMENT_CENTER); - id_label = memnew(Label(vformat(TTR("ID: %d"), value))); + id_label = memnew(Label(itos(value))); + id_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbox->add_child(id_label); Button *button = memnew(Button(TTR("Edit"))); + button->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbox->add_child(button); button->connect("pressed", callable_mp(this, &TileSourceInspectorPlugin::_show_id_edit_dialog).bind(p_object)); - add_custom_control(hbox); + ep->add_child(hbox); + add_property_editor(p_path, ep); return true; } return false; diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index 1762efeab6..6224ab72dc 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -357,6 +357,17 @@ void TileSetScenesCollectionSourceEditor::_update_scenes_list() { void TileSetScenesCollectionSourceEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_READY: { + scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object); + scenes_collection_source_inspector->add_custom_property_description("TileSetScenesCollectionProxyObject", "id", TTR("The tile's unique identifier within this TileSet. Each tile stores its source ID, so changing one may make tiles invalid.")); + scenes_collection_source_inspector->add_custom_property_description("TileSetScenesCollectionProxyObject", "name", TTR("The human-readable name for the scene collection. Use a descriptive name here for organizational purposes (such as \"obstacles\", \"decoration\", etc.).")); + + tile_inspector->edit(tile_proxy_object); + tile_inspector->add_custom_property_description("SceneTileProxyObject", "id", TTR("ID of the scene tile in the collection. Each painted tile has associated ID, so changing this property may cause your TileMaps to not display properly.")); + tile_inspector->add_custom_property_description("SceneTileProxyObject", "scene", TTR("Absolute path to the scene associated with this tile.")); + tile_inspector->add_custom_property_description("SceneTileProxyObject", "display_placeholder", TTR("If [code]true[/code], a placeholder marker will be displayed on top of the scene's preview. The marker is displayed anyway if the scene has no valid preview.")); + } break; + case NOTIFICATION_THEME_CHANGED: { scene_tile_add_button->set_icon(get_editor_theme_icon(SNAME("Add"))); scene_tile_delete_button->set_icon(get_editor_theme_icon(SNAME("Remove"))); @@ -524,8 +535,8 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { scenes_collection_source_inspector = memnew(EditorInspector); scenes_collection_source_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); + scenes_collection_source_inspector->set_use_doc_hints(true); scenes_collection_source_inspector->add_inspector_plugin(memnew(TileSourceInspectorPlugin)); - scenes_collection_source_inspector->edit(scenes_collection_source_proxy_object); middle_vbox_container->add_child(scenes_collection_source_inspector); // Tile inspector. @@ -540,7 +551,7 @@ TileSetScenesCollectionSourceEditor::TileSetScenesCollectionSourceEditor() { tile_inspector = memnew(EditorInspector); tile_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED); - tile_inspector->edit(tile_proxy_object); + tile_inspector->set_use_doc_hints(true); tile_inspector->set_use_folding(true); middle_vbox_container->add_child(tile_inspector); diff --git a/editor/register_editor_types.cpp b/editor/register_editor_types.cpp index 484fa7b85f..db1f5b439d 100644 --- a/editor/register_editor_types.cpp +++ b/editor/register_editor_types.cpp @@ -272,6 +272,8 @@ void register_editor_types() { GLOBAL_DEF("editor/import/reimport_missing_imported_files", true); GLOBAL_DEF("editor/import/use_multiple_threads", true); + GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/import/atlas_max_width", PROPERTY_HINT_RANGE, "128,8192,1,or_greater"), 2048); + GLOBAL_DEF("editor/export/convert_text_resources_to_binary", true); GLOBAL_DEF("editor/version_control/plugin_name", ""); diff --git a/methods.py b/methods.py index c22b1f11e4..69d8df1d72 100644 --- a/methods.py +++ b/methods.py @@ -1367,7 +1367,7 @@ def generate_vs_project(env, original_args, project_name="godot"): vsconf = f'{target}|{a["platform"]}' break - condition = "'$(Configuration)|$(Platform)'=='" + vsconf + "'" + condition = "'$(GodotConfiguration)|$(GodotPlatform)'=='" + vsconf + "'" properties.append("<ActiveProjectItemList>;" + ";".join(activeItems) + ";</ActiveProjectItemList>") output = f'bin\\godot{env["PROGSUFFIX"]}' @@ -1482,6 +1482,13 @@ def generate_vs_project(env, original_args, project_name="godot"): "</ProjectConfiguration>", ] + properties += [ + f"<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='{godot_target}|{proj_plat}'\">", + f" <GodotConfiguration>{godot_target}</GodotConfiguration>", + f" <GodotPlatform>{proj_plat}</GodotPlatform>", + "</PropertyGroup>", + ] + if godot_platform != "windows": configurations += [ f'<ProjectConfiguration Include="editor|{proj_plat}">', @@ -1490,6 +1497,13 @@ def generate_vs_project(env, original_args, project_name="godot"): "</ProjectConfiguration>", ] + properties += [ + f"<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='editor|{proj_plat}'\">", + f" <GodotConfiguration>editor</GodotConfiguration>", + f" <GodotPlatform>{proj_plat}</GodotPlatform>", + "</PropertyGroup>", + ] + p = f"{project_name}.{godot_platform}.{godot_target}.{godot_arch}.generated.props" imports += [ f'<Import Project="$(MSBuildProjectDirectory)\\{p}" Condition="Exists(\'$(MSBuildProjectDirectory)\\{p}\')"/>' @@ -1502,6 +1516,10 @@ def generate_vs_project(env, original_args, project_name="godot"): f"{{{proj_uuid}}}.{godot_target}|{sln_plat}.Build.0 = {godot_target}|{proj_plat}", ] + # Add an extra import for a local user props file at the end, so users can add more overrides. + imports += [ + f'<Import Project="$(MSBuildProjectDirectory)\\{project_name}.vs.user.props" Condition="Exists(\'$(MSBuildProjectDirectory)\\{project_name}.vs.user.props\')"/>' + ] section1 = sorted(section1) section2 = sorted(section2) diff --git a/misc/msvs/props.template b/misc/msvs/props.template index 9ecd49a25e..8facaf7f36 100644 --- a/misc/msvs/props.template +++ b/misc/msvs/props.template @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='%%VSCONF%%'"> + <PropertyGroup Condition="'$(GodotConfiguration)|$(GodotPlatform)'=='%%VSCONF%%'"> <NMakeBuildCommandLine>%%BUILD%%</NMakeBuildCommandLine> <NMakeReBuildCommandLine>%%REBUILD%%</NMakeReBuildCommandLine> <NMakeCleanCommandLine>%%CLEAN%%</NMakeCleanCommandLine> diff --git a/misc/msvs/vcxproj.template b/misc/msvs/vcxproj.template index a1cf22bfb9..30f29a55f8 100644 --- a/misc/msvs/vcxproj.template +++ b/misc/msvs/vcxproj.template @@ -9,23 +9,21 @@ <Keyword>MakeFileProj</Keyword> <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName> </PropertyGroup> - <PropertyGroup> - %%PROPERTIES%% - </PropertyGroup> + %%PROPERTIES%% <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration"> <ConfigurationType>Makefile</ConfigurationType> <UseOfMfc>false</UseOfMfc> <PlatformToolset>v143</PlatformToolset> - <OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\</OutDir> - <IntDir>obj\$(Platform)\$(Configuration)\</IntDir> + <OutDir>$(SolutionDir)\bin\$(GodotPlatform)\$(GodotConfiguration)\</OutDir> + <IntDir>obj\$(GodotPlatform)\$(GodotConfiguration)\</IntDir> <LayoutDir>$(OutDir)\Layout</LayoutDir> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(GodotPlatform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(GodotPlatform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup> diff --git a/scene/2d/tile_map_layer.cpp b/scene/2d/tile_map_layer.cpp index 0888852de5..bc052f9034 100644 --- a/scene/2d/tile_map_layer.cpp +++ b/scene/2d/tile_map_layer.cpp @@ -325,7 +325,7 @@ void TileMapLayer::_rendering_update() { rs->canvas_item_set_material(ci, mat->get_rid()); } rs->canvas_item_set_parent(ci, get_canvas_item()); - rs->canvas_item_set_use_parent_material(ci, true); + rs->canvas_item_set_use_parent_material(ci, !mat.is_valid()); Transform2D xform(0, rendering_quadrant->canvas_items_position); rs->canvas_item_set_transform(ci, xform); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index b0d77751af..49ac1464c2 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -991,7 +991,8 @@ void BaseMaterial3D::_update_shader() { case BILLBOARD_DISABLED: { } break; case BILLBOARD_ENABLED: { - code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(INV_VIEW_MATRIX[0], INV_VIEW_MATRIX[1], INV_VIEW_MATRIX[2], MODEL_MATRIX[3]);\n"; + // MAIN_CAM_INV_VIEW_MATRIX is inverse of the camera, even on shadow passes: this ensures the billboard faces the camera when casting shadows. + code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(MAIN_CAM_INV_VIEW_MATRIX[0], MAIN_CAM_INV_VIEW_MATRIX[1], MAIN_CAM_INV_VIEW_MATRIX[2], MODEL_MATRIX[3]);\n"; if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; @@ -999,10 +1000,11 @@ void BaseMaterial3D::_update_shader() { code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n"; } break; case BILLBOARD_FIXED_Y: { - code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), INV_VIEW_MATRIX[2].xyz)), 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(normalize(cross(INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0), MODEL_MATRIX[3]);\n"; + // MAIN_CAM_INV_VIEW_MATRIX is inverse of the camera, even on shadow passes: this ensures the billboard faces the camera when casting shadows. + code += " MODELVIEW_MATRIX = VIEW_MATRIX * mat4(vec4(normalize(cross(vec3(0.0, 1.0, 0.0), MAIN_CAM_INV_VIEW_MATRIX[2].xyz)), 0.0), vec4(0.0, 1.0, 0.0, 0.0), vec4(normalize(cross(MAIN_CAM_INV_VIEW_MATRIX[0].xyz, vec3(0.0, 1.0, 0.0))), 0.0), MODEL_MATRIX[3]);\n"; if (flags[FLAG_BILLBOARD_KEEP_SCALE]) { - code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0),vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; + code += " MODELVIEW_MATRIX = MODELVIEW_MATRIX * mat4(vec4(length(MODEL_MATRIX[0].xyz), 0.0, 0.0, 0.0), vec4(0.0, length(MODEL_MATRIX[1].xyz), 0.0, 0.0), vec4(0.0, 0.0, length(MODEL_MATRIX[2].xyz), 0.0), vec4(0.0, 0.0, 0.0, 1.0));\n"; } code += " MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);\n"; } break; diff --git a/scene/resources/navigation_polygon.h b/scene/resources/navigation_polygon.h index cfd9b497e0..f20d510b93 100644 --- a/scene/resources/navigation_polygon.h +++ b/scene/resources/navigation_polygon.h @@ -94,7 +94,7 @@ public: uint32_t parsed_collision_mask = 0xFFFFFFFF; SourceGeometryMode source_geometry_mode = SOURCE_GEOMETRY_ROOT_NODE_CHILDREN; - StringName source_geometry_group_name = "navigation_polygon_source_group"; + StringName source_geometry_group_name = "navigation_polygon_source_geometry_group"; void set_vertices(const Vector<Vector2> &p_vertices); Vector<Vector2> get_vertices() const; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 3bd0fb6e2b..e972d91072 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1403,7 +1403,7 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo //cube shadows are rendered in their own way for (const int &index : p_render_data->cube_shadows) { - _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size); + _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); } if (p_render_data->directional_shadows.size()) { @@ -1433,11 +1433,11 @@ void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, boo //render directional shadows for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, viewport_size); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); } //render positional shadows for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, viewport_size); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, viewport_size, p_render_data->scene_data->cam_transform); } _render_shadow_process(); @@ -2268,7 +2268,7 @@ void RenderForwardClustered::_render_buffers_debug_draw(const RenderDataRD *p_re } } -void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size) { +void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); @@ -2423,7 +2423,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas if (render_cubemap) { //rendering to cubemap - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_viewport_size); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_viewport_size, p_main_cam_transform); if (finalize_cubemap) { _render_shadow_process(); _render_shadow_end(); @@ -2441,7 +2441,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas } else { //render shadow - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_viewport_size); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, reverse_cull_face, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_viewport_size, p_main_cam_transform); } } @@ -2454,7 +2454,7 @@ void RenderForwardClustered::_render_shadow_begin() { scene_state.instance_data[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size) { +void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -2470,6 +2470,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page scene_data.opaque_prepass_threshold = 0.1f; scene_data.time = time; scene_data.time_step = time_step; + scene_data.main_cam_transform = p_main_cam_transform; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -2561,6 +2562,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con scene_data.opaque_prepass_threshold = 0.0; scene_data.time = time; scene_data.time_step = time_step; + scene_data.main_cam_transform = p_cam_transform; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -2605,6 +2607,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform scene_data.emissive_exposure_normalization = p_exposure_normalization; scene_data.time = time; scene_data.time_step = time_step; + scene_data.main_cam_transform = p_cam_transform; RenderDataRD render_data; render_data.scene_data = &scene_data; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 5af213bc02..be55341102 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -591,9 +591,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { /* Render shadows */ - void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1)); + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_begin(); - void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1)); + void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Size2i &p_viewport_size = Size2i(1, 1), const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_process(); void _render_shadow_end(); diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index abb0359f0d..55c6c420eb 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -559,6 +559,7 @@ void SceneShaderForwardClustered::init(const String p_defines) { actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; + actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix"; actions.renames["VERTEX"] = "vertex"; actions.renames["NORMAL"] = "normal"; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index db8c1acdbe..29c5deb6c2 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -608,7 +608,7 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { //cube shadows are rendered in their own way for (const int &index : p_render_data->cube_shadows) { - _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); + _render_shadow_pass(p_render_data->render_shadows[index].light, p_render_data->shadow_atlas, p_render_data->render_shadows[index].pass, p_render_data->render_shadows[index].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info, p_render_data->scene_data->cam_transform); } if (p_render_data->directional_shadows.size()) { @@ -629,11 +629,11 @@ void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { //render directional shadows for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info, p_render_data->scene_data->cam_transform); } //render positional shadows for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) { - _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info); + _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info, p_render_data->scene_data->cam_transform); } _render_shadow_process(); @@ -1068,7 +1068,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color /* these are being called from RendererSceneRenderRD::_pre_opaque_render */ -void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) { +void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); @@ -1222,7 +1222,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i if (render_cubemap) { //rendering to cubemap - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info, p_main_cam_transform); if (finalize_cubemap) { _render_shadow_process(); _render_shadow_end(); @@ -1241,7 +1241,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i } else { //render shadow - _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info); + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info, p_main_cam_transform); } } @@ -1253,7 +1253,7 @@ void RenderForwardMobile::_render_shadow_begin() { render_list[RENDER_LIST_SECONDARY].clear(); } -void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info) { +void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Transform3D &p_main_cam_transform) { uint32_t shadow_pass_index = scene_state.shadow_passes.size(); SceneState::ShadowPass shadow_pass; @@ -1274,6 +1274,7 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr scene_data.opaque_prepass_threshold = 0.1; scene_data.time = time; scene_data.time_step = time_step; + scene_data.main_cam_transform = p_main_cam_transform; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -1363,6 +1364,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c scene_data.emissive_exposure_normalization = p_exposure_normalization; scene_data.time = time; scene_data.time_step = time_step; + scene_data.main_cam_transform = p_cam_transform; RenderDataRD render_data; render_data.scene_data = &scene_data; @@ -1488,6 +1490,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const scene_data.opaque_prepass_threshold = 0.0; scene_data.time = time; scene_data.time_step = time_step; + scene_data.main_cam_transform = p_cam_transform; RenderDataRD render_data; render_data.scene_data = &scene_data; diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index f1f6bb3db4..ba5fefc83f 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -177,9 +177,9 @@ private: /* Render shadows */ - void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_begin(); - void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D()); void _render_shadow_process(); void _render_shadow_end(); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp index 96cd5052c8..3592ee2f6d 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp @@ -463,6 +463,7 @@ void SceneShaderForwardMobile::init(const String p_defines) { actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; actions.renames["MODELVIEW_MATRIX"] = "modelview"; actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; + actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix"; actions.renames["VERTEX"] = "vertex"; actions.renames["NORMAL"] = "normal"; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 3b05431f4a..35c0bdd595 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -1005,6 +1005,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render scene_data.cam_orthogonal = p_camera_data->is_orthogonal; scene_data.camera_visible_layers = p_camera_data->visible_layers; scene_data.taa_jitter = p_camera_data->taa_jitter; + scene_data.main_cam_transform = p_camera_data->main_transform; scene_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl index f42fafc68a..70e670c3f7 100644 --- a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl @@ -14,6 +14,9 @@ struct SceneData { highp mat4 inv_projection_matrix_view[MAX_VIEWS]; highp vec4 eye_offset[MAX_VIEWS]; + // Used for billboards to cast correct shadows. + highp mat4 main_cam_inv_view_matrix; + highp vec2 viewport_size; highp vec2 screen_pixel_size; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp index f2231664fa..506e78bae9 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp @@ -76,6 +76,8 @@ void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p ubo.eye_offset[v][3] = 0.0; } + RendererRD::MaterialStorage::store_transform(main_cam_transform, ubo.main_cam_inv_view_matrix); + ubo.taa_jitter[0] = taa_jitter.x; ubo.taa_jitter[1] = taa_jitter.y; diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h index f183207b57..f93f22816b 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h @@ -48,6 +48,9 @@ public: uint32_t camera_visible_layers; bool cam_orthogonal = false; + // For billboards to cast correct shadows. + Transform3D main_cam_transform; + // For stereo rendering uint32_t view_count = 1; Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; @@ -94,6 +97,8 @@ private: float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4]; + float main_cam_inv_view_matrix[16]; + float viewport_size[2]; float screen_pixel_size[2]; diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index 1272c59a2d..aff874f452 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -97,6 +97,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MAIN_CAM_INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3; |