summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--AUTHORS.md10
-rw-r--r--DONORS.md132
-rw-r--r--doc/classes/BaseMaterial3D.xml1
-rw-r--r--doc/classes/ProjectSettings.xml3
-rw-r--r--doc/classes/SpriteBase3D.xml1
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp54
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.h2
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp12
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h7
-rw-r--r--drivers/gles3/shaders/scene.glsl6
-rw-r--r--drivers/gles3/storage/material_storage.cpp1
-rw-r--r--drivers/windows/file_access_windows.cpp7
-rw-r--r--editor/animation_bezier_editor.cpp4
-rw-r--r--editor/animation_track_editor.cpp4
-rw-r--r--editor/animation_track_editor.h3
-rw-r--r--editor/editor_help.cpp7
-rw-r--r--editor/editor_help.h4
-rw-r--r--editor/editor_inspector.cpp21
-rw-r--r--editor/editor_inspector.h4
-rw-r--r--editor/import/resource_importer_texture_atlas.cpp9
-rw-r--r--editor/plugins/script_text_editor.cpp5
-rw-r--r--editor/plugins/tiles/tile_set_atlas_source_editor.cpp35
-rw-r--r--editor/plugins/tiles/tile_set_editor.cpp11
-rw-r--r--editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp15
-rw-r--r--editor/register_editor_types.cpp2
-rw-r--r--methods.py20
-rw-r--r--misc/msvs/props.template2
-rw-r--r--misc/msvs/vcxproj.template10
-rw-r--r--scene/2d/tile_map_layer.cpp2
-rw-r--r--scene/resources/material.cpp8
-rw-r--r--scene/resources/navigation_polygon.h2
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp17
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h4
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp1
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp17
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h4
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp1
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp1
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_data_inc.glsl3
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp2
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h5
-rw-r--r--servers/rendering/shader_types.cpp1
43 files changed, 307 insertions, 154 deletions
diff --git a/.mailmap b/.mailmap
index 73109a78a9..731f224bb6 100644
--- a/.mailmap
+++ b/.mailmap
@@ -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)
diff --git a/DONORS.md b/DONORS.md
index 3b319b04b2..b74232c461 100644
--- a/DONORS.md
+++ b/DONORS.md
@@ -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;