summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitattributes7
-rw-r--r--doc/classes/GeometryInstance3D.xml3
-rw-r--r--doc/classes/RenderingServer.xml23
-rw-r--r--doc/classes/Viewport.xml15
-rw-r--r--doc/classes/XRVRS.xml30
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.cpp4
-rw-r--r--drivers/d3d12/rendering_device_driver_d3d12.h1
-rw-r--r--drivers/gles3/storage/texture_storage.h2
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.cpp8
-rw-r--r--drivers/vulkan/rendering_device_driver_vulkan.h1
-rw-r--r--editor/editor_settings.cpp8
-rw-r--r--editor/gui/editor_file_dialog.cpp8
-rw-r--r--editor/import/3d/resource_importer_scene.cpp2
-rw-r--r--editor/import/3d/resource_importer_scene.h4
-rw-r--r--editor/plugins/text_shader_editor.cpp2
-rw-r--r--modules/fbx/fbx_document.cpp10
-rw-r--r--modules/fbx/fbx_state.h1
-rw-r--r--modules/mobile_vr/doc_classes/MobileVRInterface.xml8
-rw-r--r--modules/mobile_vr/mobile_vr_interface.cpp54
-rw-r--r--modules/mobile_vr/mobile_vr_interface.h11
-rw-r--r--modules/mono/.editorconfig4
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln11
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj2
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj14
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.sln12
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj2
-rw-r--r--modules/mono/editor/bindings_generator.cpp14
-rw-r--r--modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Godot.SourceGenerators.Internal.csproj2
-rw-r--r--modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj26
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp.sln15
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs61
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj2
-rw-r--r--modules/openxr/doc_classes/OpenXRInterface.xml8
-rw-r--r--modules/openxr/extensions/openxr_eye_gaze_interaction.cpp36
-rw-r--r--modules/openxr/extensions/openxr_eye_gaze_interaction.h6
-rw-r--r--modules/openxr/openxr_api.cpp85
-rw-r--r--modules/openxr/openxr_api.h4
-rw-r--r--modules/openxr/openxr_interface.cpp44
-rw-r--r--modules/openxr/openxr_interface.h10
-rw-r--r--scene/3d/skeleton_3d.cpp39
-rw-r--r--scene/3d/skeleton_3d.h38
-rw-r--r--scene/3d/visual_instance_3d.cpp9
-rw-r--r--scene/main/viewport.cpp35
-rw-r--r--scene/main/viewport.h12
-rw-r--r--scene/resources/syntax_highlighter.cpp6
-rw-r--r--scene/resources/syntax_highlighter.h4
-rw-r--r--servers/register_server_types.cpp1
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h2
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp22
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.h7
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl46
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp14
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h3
-rw-r--r--servers/rendering/renderer_viewport.cpp7
-rw-r--r--servers/rendering/renderer_viewport.h1
-rw-r--r--servers/rendering/rendering_device.cpp8
-rw-r--r--servers/rendering/rendering_device.h2
-rw-r--r--servers/rendering/rendering_device_commons.h2
-rw-r--r--servers/rendering/rendering_server_default.h1
-rw-r--r--servers/rendering/storage/texture_storage.h2
-rw-r--r--servers/rendering_server.cpp8
-rw-r--r--servers/rendering_server.h9
-rw-r--r--servers/xr/xr_interface.cpp83
-rw-r--r--servers/xr/xr_interface.h13
-rw-r--r--servers/xr/xr_vrs.cpp151
-rw-r--r--servers/xr/xr_vrs.h67
76 files changed, 887 insertions, 285 deletions
diff --git a/.gitattributes b/.gitattributes
index ccc576c2e1..5af3e121a8 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -5,12 +5,13 @@ thirdparty/* linguist-vendored
# Normalize EOL for all files that Git considers text files
* text=auto eol=lf
-# Except for bat files, which are Windows only files
+# Except for Windows-only / Visual Studio files
*.bat eol=crlf
+*.sln eol=crlf
+*.csproj eol=crlf
+misc/msvs/*.template eol=crlf
# And some test files where the EOL matters
*.test.txt -text
-# And also the templates for Visual Studio files, which VS will always force CRLF on
-/misc/msvs/*.template eol=crlf
# The above only works properly for Git 2.10+, so for older versions
# we need to manually list the binary files we don't want modified.
diff --git a/doc/classes/GeometryInstance3D.xml b/doc/classes/GeometryInstance3D.xml
index e52a3d7683..f4075af186 100644
--- a/doc/classes/GeometryInstance3D.xml
+++ b/doc/classes/GeometryInstance3D.xml
@@ -66,6 +66,7 @@
The transparency applied to the whole geometry (as a multiplier of the materials' existing transparency). [code]0.0[/code] is fully opaque, while [code]1.0[/code] is fully transparent. Values greater than [code]0.0[/code] (exclusive) will force the geometry's materials to go through the transparent pipeline, which is slower to render and can exhibit rendering issues due to incorrect transparency sorting. However, unlike using a transparent material, setting [member transparency] to a value greater than [code]0.0[/code] (exclusive) will [i]not[/i] disable shadow rendering.
In spatial shaders, [code]1.0 - transparency[/code] is set as the default value of the [code]ALPHA[/code] built-in.
[b]Note:[/b] [member transparency] is clamped between [code]0.0[/code] and [code]1.0[/code], so this property cannot be used to make transparent materials more opaque than they originally are.
+ [b]Note:[/b] Only supported when using the Forward+ rendering method. When using the Mobile or Compatibility rendering method, [member transparency] is ignored and is considered as always being [code]0.0[/code].
</member>
<member name="visibility_range_begin" type="float" setter="set_visibility_range_begin" getter="get_visibility_range_begin" default="0.0" keywords="lod_begin, hlod_begin">
Starting distance from which the GeometryInstance3D will be visible, taking [member visibility_range_begin_margin] into account as well. The default value of 0 is used to disable the range check.
@@ -130,9 +131,11 @@
</constant>
<constant name="VISIBILITY_RANGE_FADE_SELF" value="1" enum="VisibilityRangeFadeMode">
Will fade-out itself when reaching the limits of its own visibility range. This is slower than [constant VISIBILITY_RANGE_FADE_DISABLED], but it can provide smoother transitions. The fading range is determined by [member visibility_range_begin_margin] and [member visibility_range_end_margin].
+ [b]Note:[/b] Only supported when using the Forward+ rendering method. When using the Mobile or Compatibility rendering method, this mode acts like [constant VISIBILITY_RANGE_FADE_DISABLED] but with hysteresis disabled.
</constant>
<constant name="VISIBILITY_RANGE_FADE_DEPENDENCIES" value="2" enum="VisibilityRangeFadeMode">
Will fade-in its visibility dependencies (see [member Node3D.visibility_parent]) when reaching the limits of its own visibility range. This is slower than [constant VISIBILITY_RANGE_FADE_DISABLED], but it can provide smoother transitions. The fading range is determined by [member visibility_range_begin_margin] and [member visibility_range_end_margin].
+ [b]Note:[/b] Only supported when using the Forward+ rendering method. When using the Mobile or Compatibility rendering method, this mode acts like [constant VISIBILITY_RANGE_FADE_DISABLED] but with hysteresis disabled.
</constant>
</constants>
</class>
diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 519bba4e7c..27bf2587d4 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -4036,6 +4036,15 @@
The texture to use when the VRS mode is set to [constant RenderingServer.VIEWPORT_VRS_TEXTURE]. Equivalent to [member ProjectSettings.rendering/vrs/texture].
</description>
</method>
+ <method name="viewport_set_vrs_update_mode">
+ <return type="void" />
+ <param index="0" name="viewport" type="RID" />
+ <param index="1" name="mode" type="int" enum="RenderingServer.ViewportVRSUpdateMode" />
+ <description>
+ Sets the update mode for Variable Rate Shading (VRS) for the viewport. VRS requires the input texture to be converted to the format usable by the VRS method supported by the hardware. The update mode defines how often this happens. If the GPU does not support VRS, or VRS is not enabled, this property is ignored.
+ If set to [constant RenderingServer.VIEWPORT_VRS_UPDATE_ONCE], the input texture is copied once and the mode is changed to [constant RenderingServer.VIEWPORT_VRS_UPDATE_DISABLED].
+ </description>
+ </method>
<method name="visibility_notifier_create">
<return type="RID" />
<description>
@@ -4976,11 +4985,23 @@
Variable rate shading uses a texture. Note, for stereoscopic use a texture atlas with a texture for each view.
</constant>
<constant name="VIEWPORT_VRS_XR" value="2" enum="ViewportVRSMode">
- Variable rate shading texture is supplied by the primary [XRInterface].
+ Variable rate shading texture is supplied by the primary [XRInterface]. Note that this may override the update mode.
</constant>
<constant name="VIEWPORT_VRS_MAX" value="3" enum="ViewportVRSMode">
Represents the size of the [enum ViewportVRSMode] enum.
</constant>
+ <constant name="VIEWPORT_VRS_UPDATE_DISABLED" value="0" enum="ViewportVRSUpdateMode">
+ The input texture for variable rate shading will not be processed.
+ </constant>
+ <constant name="VIEWPORT_VRS_UPDATE_ONCE" value="1" enum="ViewportVRSUpdateMode">
+ The input texture for variable rate shading will be processed once.
+ </constant>
+ <constant name="VIEWPORT_VRS_UPDATE_ALWAYS" value="2" enum="ViewportVRSUpdateMode">
+ The input texture for variable rate shading will be processed each frame.
+ </constant>
+ <constant name="VIEWPORT_VRS_UPDATE_MAX" value="3" enum="ViewportVRSUpdateMode">
+ Represents the size of the [enum ViewportVRSUpdateMode] enum.
+ </constant>
<constant name="SKY_MODE_AUTOMATIC" value="0" enum="SkyMode">
Automatically selects the appropriate process mode based on your sky shader. If your shader uses [code]TIME[/code] or [code]POSITION[/code], this will use [constant SKY_MODE_REALTIME]. If your shader uses any of the [code]LIGHT_*[/code] variables or any custom uniforms, this uses [constant SKY_MODE_INCREMENTAL]. Otherwise, this defaults to [constant SKY_MODE_QUALITY].
</constant>
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index cf33eac9c7..b288ee7ff6 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -407,6 +407,9 @@
- 8×8 = rgb(255, 255, 0) - #ffff00 - Not supported on most hardware
[/codeblock]
</member>
+ <member name="vrs_update_mode" type="int" setter="set_vrs_update_mode" getter="get_vrs_update_mode" enum="Viewport.VRSUpdateMode" default="1">
+ Sets the update mode for Variable Rate Shading (VRS) for the viewport. VRS requires the input texture to be converted to the format usable by the VRS method supported by the hardware. The update mode defines how often this happens. If the GPU does not support VRS, or VRS is not enabled, this property is ignored.
+ </member>
<member name="world_2d" type="World2D" setter="set_world_2d" getter="get_world_2d">
The custom [World2D] which can be used as 2D environment source.
</member>
@@ -664,5 +667,17 @@
<constant name="VRS_MAX" value="3" enum="VRSMode">
Represents the size of the [enum VRSMode] enum.
</constant>
+ <constant name="VRS_UPDATE_DISABLED" value="0" enum="VRSUpdateMode">
+ The input texture for variable rate shading will not be processed.
+ </constant>
+ <constant name="VRS_UPDATE_ONCE" value="1" enum="VRSUpdateMode">
+ The input texture for variable rate shading will be processed once.
+ </constant>
+ <constant name="VRS_UPDATE_ALWAYS" value="2" enum="VRSUpdateMode">
+ The input texture for variable rate shading will be processed each frame.
+ </constant>
+ <constant name="VRS_UPDATE_MAX" value="3" enum="VRSUpdateMode">
+ Represents the size of the [enum VRSUpdateMode] enum.
+ </constant>
</constants>
</class>
diff --git a/doc/classes/XRVRS.xml b/doc/classes/XRVRS.xml
new file mode 100644
index 0000000000..b19b461fab
--- /dev/null
+++ b/doc/classes/XRVRS.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="XRVRS" inherits="Object" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
+ <brief_description>
+ Helper class for XR interfaces that generates VRS images.
+ </brief_description>
+ <description>
+ This class is used by various XR interfaces to generate VRS textures that can be used to speed up rendering.
+ </description>
+ <tutorials>
+ </tutorials>
+ <methods>
+ <method name="make_vrs_texture">
+ <return type="RID" />
+ <param index="0" name="target_size" type="Vector2" />
+ <param index="1" name="eye_foci" type="PackedVector2Array" />
+ <description>
+ Generates the VRS texture based on a render [param target_size] adjusted by our VRS tile size. For each eyes focal point passed in [param eye_foci] a layer is created. Focal point should be in NDC.
+ The result will be cached, requesting a VRS texture with unchanged parameters and settings will return the cached RID.
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="vrs_min_radius" type="float" setter="set_vrs_min_radius" getter="get_vrs_min_radius" default="20.0">
+ The minimum radius around the focal point where full quality is guaranteed if VRS is used as a percentage of screen size.
+ </member>
+ <member name="vrs_strength" type="float" setter="set_vrs_strength" getter="get_vrs_strength" default="1.0">
+ The strength used to calculate the VRS density map. The greater this value, the more noticeable VRS is.
+ </member>
+ </members>
+</class>
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.cpp b/drivers/d3d12/rendering_device_driver_d3d12.cpp
index fc7aa62aae..9407826ebf 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.cpp
+++ b/drivers/d3d12/rendering_device_driver_d3d12.cpp
@@ -5912,6 +5912,9 @@ uint64_t RenderingDeviceDriverD3D12::limit_get(Limit p_limit) {
case LIMIT_VRS_TEXEL_WIDTH:
case LIMIT_VRS_TEXEL_HEIGHT:
return vrs_capabilities.ss_image_tile_size;
+ case LIMIT_VRS_MAX_FRAGMENT_WIDTH:
+ case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
+ return vrs_capabilities.ss_max_fragment_size;
default: {
#ifdef DEV_ENABLED
WARN_PRINT("Returning maximum value for unknown limit " + itos(p_limit) + ".");
@@ -6218,6 +6221,7 @@ Error RenderingDeviceDriverD3D12::_check_capabilities() {
vrs_capabilities.primitive_in_multiviewport = options6.PerPrimitiveShadingRateSupportedWithViewportIndexing;
vrs_capabilities.ss_image_supported = true;
vrs_capabilities.ss_image_tile_size = options6.ShadingRateImageTileSize;
+ vrs_capabilities.ss_max_fragment_size = 8; // TODO figure out if this is supplied and/or needed
vrs_capabilities.additional_rates_supported = options6.AdditionalShadingRatesSupported;
}
}
diff --git a/drivers/d3d12/rendering_device_driver_d3d12.h b/drivers/d3d12/rendering_device_driver_d3d12.h
index 61da9a5169..8e1223bdaa 100644
--- a/drivers/d3d12/rendering_device_driver_d3d12.h
+++ b/drivers/d3d12/rendering_device_driver_d3d12.h
@@ -105,6 +105,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
bool primitive_in_multiviewport = false;
bool ss_image_supported = false; // We can provide a density map attachment on our framebuffer.
uint32_t ss_image_tile_size = 0;
+ uint32_t ss_max_fragment_size = 0;
bool additional_rates_supported = false;
};
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index ef310262c7..8a03d72b9b 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -672,6 +672,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {}
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; }
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override {}
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_UPDATE_DISABLED; }
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
diff --git a/drivers/vulkan/rendering_device_driver_vulkan.cpp b/drivers/vulkan/rendering_device_driver_vulkan.cpp
index 803555cb07..339d0782bf 100644
--- a/drivers/vulkan/rendering_device_driver_vulkan.cpp
+++ b/drivers/vulkan/rendering_device_driver_vulkan.cpp
@@ -758,11 +758,13 @@ Error RenderingDeviceDriverVulkan::_check_device_capabilities() {
vrs_capabilities.min_texel_size.y = vrs_properties.minFragmentShadingRateAttachmentTexelSize.height;
vrs_capabilities.max_texel_size.x = vrs_properties.maxFragmentShadingRateAttachmentTexelSize.width;
vrs_capabilities.max_texel_size.y = vrs_properties.maxFragmentShadingRateAttachmentTexelSize.height;
+ vrs_capabilities.max_fragment_size.x = vrs_properties.maxFragmentSize.width; // either 4 or 8
+ vrs_capabilities.max_fragment_size.y = vrs_properties.maxFragmentSize.height; // generally the same as width
// We'll attempt to default to a texel size of 16x16.
vrs_capabilities.texel_size = Vector2i(16, 16).clamp(vrs_capabilities.min_texel_size, vrs_capabilities.max_texel_size);
- print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")"));
+ print_verbose(String(" Attachment fragment shading rate") + String(", min texel size: (") + itos(vrs_capabilities.min_texel_size.x) + String(", ") + itos(vrs_capabilities.min_texel_size.y) + String(")") + String(", max texel size: (") + itos(vrs_capabilities.max_texel_size.x) + String(", ") + itos(vrs_capabilities.max_texel_size.y) + String(")") + String(", max fragment size: (") + itos(vrs_capabilities.max_fragment_size.x) + String(", ") + itos(vrs_capabilities.max_fragment_size.y) + String(")"));
}
} else {
@@ -4887,6 +4889,10 @@ uint64_t RenderingDeviceDriverVulkan::limit_get(Limit p_limit) {
return vrs_capabilities.texel_size.x;
case LIMIT_VRS_TEXEL_HEIGHT:
return vrs_capabilities.texel_size.y;
+ case LIMIT_VRS_MAX_FRAGMENT_WIDTH:
+ return vrs_capabilities.max_fragment_size.x;
+ case LIMIT_VRS_MAX_FRAGMENT_HEIGHT:
+ return vrs_capabilities.max_fragment_size.y;
default:
ERR_FAIL_V(0);
}
diff --git a/drivers/vulkan/rendering_device_driver_vulkan.h b/drivers/vulkan/rendering_device_driver_vulkan.h
index 70c4cebba5..e70019962a 100644
--- a/drivers/vulkan/rendering_device_driver_vulkan.h
+++ b/drivers/vulkan/rendering_device_driver_vulkan.h
@@ -87,6 +87,7 @@ class RenderingDeviceDriverVulkan : public RenderingDeviceDriver {
Size2i min_texel_size;
Size2i max_texel_size;
+ Size2i max_fragment_size;
Size2i texel_size; // The texel size we'll use
};
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index f3c5bf2ea8..cec50ac30f 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -1643,7 +1643,9 @@ Ref<Shortcut> ED_GET_SHORTCUT(const String &p_path) {
}
void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_keycode, bool p_physical) {
- ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet.");
+ if (!EditorSettings::get_singleton()) {
+ return;
+ }
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE with invalid shortcut: " + p_path);
@@ -1655,7 +1657,9 @@ void ED_SHORTCUT_OVERRIDE(const String &p_path, const String &p_feature, Key p_k
}
void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, const PackedInt32Array &p_keycodes, bool p_physical) {
- ERR_FAIL_NULL_MSG(EditorSettings::get_singleton(), "EditorSettings not instantiated yet.");
+ if (!EditorSettings::get_singleton()) {
+ return;
+ }
Ref<Shortcut> sc = EditorSettings::get_singleton()->get_shortcut(p_path);
ERR_FAIL_COND_MSG(!sc.is_valid(), "Used ED_SHORTCUT_OVERRIDE_ARRAY with invalid shortcut: " + p_path);
diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp
index a7cdb65145..f0ad2946d0 100644
--- a/editor/gui/editor_file_dialog.cpp
+++ b/editor/gui/editor_file_dialog.cpp
@@ -2086,11 +2086,9 @@ EditorFileDialog::EditorFileDialog() {
ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KeyModifierMask::CMD_OR_CTRL | Key::UP);
ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KeyModifierMask::CMD_OR_CTRL | Key::DOWN);
- if (EditorSettings::get_singleton()) {
- ED_SHORTCUT_OVERRIDE("file_dialog/toggle_hidden_files", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::PERIOD);
- ED_SHORTCUT_OVERRIDE("file_dialog/toggle_favorite", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::F);
- ED_SHORTCUT_OVERRIDE("file_dialog/toggle_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::V);
- }
+ ED_SHORTCUT_OVERRIDE("file_dialog/toggle_hidden_files", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::PERIOD);
+ ED_SHORTCUT_OVERRIDE("file_dialog/toggle_favorite", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::F);
+ ED_SHORTCUT_OVERRIDE("file_dialog/toggle_mode", "macos", KeyModifierMask::META | KeyModifierMask::CTRL | Key::V);
pathhb = memnew(HBoxContainer);
vbc->add_child(pathhb);
diff --git a/editor/import/3d/resource_importer_scene.cpp b/editor/import/3d/resource_importer_scene.cpp
index 2560d43241..bb833b1b2c 100644
--- a/editor/import/3d/resource_importer_scene.cpp
+++ b/editor/import/3d/resource_importer_scene.cpp
@@ -1949,7 +1949,7 @@ void ResourceImporterScene::get_internal_import_options(InternalImportCategory p
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate/physics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "generate/navmesh", PROPERTY_HINT_ENUM, "Disabled,Mesh + NavMesh,NavMesh Only"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/body_type", PROPERTY_HINT_ENUM, "Static,Dynamic,Area"), 0));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/shape_type", PROPERTY_HINT_ENUM, "Decompose Convex,Simple Convex,Trimesh,Box,Sphere,Cylinder,Capsule", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/shape_type", PROPERTY_HINT_ENUM, "Decompose Convex,Simple Convex,Trimesh,Box,Sphere,Cylinder,Capsule", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), 2));
r_options->push_back(ImportOption(PropertyInfo(Variant::OBJECT, "physics/physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), Variant()));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), 1));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "physics/mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), 1));
diff --git a/editor/import/3d/resource_importer_scene.h b/editor/import/3d/resource_importer_scene.h
index b55ff94309..bbf2d20163 100644
--- a/editor/import/3d/resource_importer_scene.h
+++ b/editor/import/3d/resource_importer_scene.h
@@ -323,7 +323,7 @@ public:
template <typename M>
Vector<Ref<Shape3D>> ResourceImporterScene::get_collision_shapes(const Ref<ImporterMesh> &p_mesh, const M &p_options, float p_applied_root_scale) {
ERR_FAIL_COND_V(p_mesh.is_null(), Vector<Ref<Shape3D>>());
- ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX;
+ ShapeType generate_shape_type = SHAPE_TYPE_TRIMESH;
if (p_options.has(SNAME("physics/shape_type"))) {
generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int();
}
@@ -481,7 +481,7 @@ template <typename M>
Transform3D ResourceImporterScene::get_collision_shapes_transform(const M &p_options) {
Transform3D transform;
- ShapeType generate_shape_type = SHAPE_TYPE_DECOMPOSE_CONVEX;
+ ShapeType generate_shape_type = SHAPE_TYPE_TRIMESH;
if (p_options.has(SNAME("physics/shape_type"))) {
generate_shape_type = (ShapeType)p_options[SNAME("physics/shape_type")].operator int();
}
diff --git a/editor/plugins/text_shader_editor.cpp b/editor/plugins/text_shader_editor.cpp
index 83a1700306..a1d1df0f83 100644
--- a/editor/plugins/text_shader_editor.cpp
+++ b/editor/plugins/text_shader_editor.cpp
@@ -334,6 +334,8 @@ void ShaderTextEditor::_load_theme_settings() {
warnings_panel->add_theme_font_override("normal_font", EditorNode::get_singleton()->get_editor_theme()->get_font(SNAME("main"), EditorStringName(EditorFonts)));
warnings_panel->add_theme_font_size_override("normal_font_size", EditorNode::get_singleton()->get_editor_theme()->get_font_size(SNAME("main_size"), EditorStringName(EditorFonts)));
}
+
+ syntax_highlighter->set_uint_suffix_enabled();
}
void ShaderTextEditor::_check_shader_mode() {
diff --git a/modules/fbx/fbx_document.cpp b/modules/fbx/fbx_document.cpp
index 5f94a80566..6e9b85dc35 100644
--- a/modules/fbx/fbx_document.cpp
+++ b/modules/fbx/fbx_document.cpp
@@ -693,10 +693,7 @@ Error FBXDocument::_parse_meshes(Ref<FBXState> p_state) {
// Find the first imported skin deformer
for (ufbx_skin_deformer *fbx_skin : fbx_mesh->skin_deformers) {
- if (!p_state->skin_indices.has(fbx_skin->typed_id)) {
- continue;
- }
- GLTFSkinIndex skin_i = p_state->skin_indices[fbx_skin->typed_id];
+ GLTFSkinIndex skin_i = p_state->original_skin_indices[fbx_skin->typed_id];
if (skin_i < 0) {
continue;
}
@@ -2341,7 +2338,7 @@ Error FBXDocument::_parse_skins(Ref<FBXState> p_state) {
HashMap<GLTFNodeIndex, bool> joint_mapping;
for (const ufbx_skin_deformer *fbx_skin : fbx_scene->skin_deformers) {
- if (fbx_skin->clusters.count == 0) {
+ if (fbx_skin->clusters.count == 0 || fbx_skin->weights.count == 0) {
p_state->skin_indices.push_back(-1);
continue;
}
@@ -2387,8 +2384,9 @@ Error FBXDocument::_parse_skins(Ref<FBXState> p_state) {
}
}
}
+ p_state->original_skin_indices = p_state->skin_indices.duplicate();
Error err = SkinTool::_asset_parse_skins(
- p_state->skin_indices.duplicate(),
+ p_state->original_skin_indices,
p_state->skins.duplicate(),
p_state->nodes.duplicate(),
p_state->skin_indices,
diff --git a/modules/fbx/fbx_state.h b/modules/fbx/fbx_state.h
index d10550c228..e52f47e0db 100644
--- a/modules/fbx/fbx_state.h
+++ b/modules/fbx/fbx_state.h
@@ -53,6 +53,7 @@ class FBXState : public GLTFState {
HashMap<Pair<uint64_t, uint64_t>, GLTFTextureIndex, PairHash<uint64_t, uint64_t>> albedo_transparency_textures;
Vector<GLTFSkinIndex> skin_indices;
+ Vector<GLTFSkinIndex> original_skin_indices;
HashMap<ObjectID, GLTFSkeletonIndex> skeleton3d_to_fbx_skeleton;
HashMap<ObjectID, HashMap<ObjectID, GLTFSkinIndex>> skin_and_skeleton3d_to_fbx_skin;
HashSet<String> unique_mesh_names; // Not in GLTFState because GLTFState prefixes mesh names with the scene name (or _)
diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
index 8338054142..0dbe06d220 100644
--- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml
+++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml
@@ -40,6 +40,14 @@
<member name="oversample" type="float" setter="set_oversample" getter="get_oversample" default="1.5">
The oversample setting. Because of the lens distortion we have to render our buffers at a higher resolution then the screen can natively handle. A value between 1.5 and 2.0 often provides good results but at the cost of performance.
</member>
+ <member name="vrs_min_radius" type="float" setter="set_vrs_min_radius" getter="get_vrs_min_radius" default="20.0">
+ The minimum radius around the focal point where full quality is guaranteed if VRS is used as a percentage of screen size.
+ [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR].
+ </member>
+ <member name="vrs_strength" type="float" setter="set_vrs_strength" getter="get_vrs_strength" default="1.0">
+ The strength used to calculate the VRS density map. The greater this value, the more noticeable VRS is. This improves performance at the cost of quality.
+ [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR].
+ </member>
<member name="xr_play_area_mode" type="int" setter="set_play_area_mode" getter="get_play_area_mode" overrides="XRInterface" enum="XRInterface.PlayAreaMode" default="1" />
</members>
</class>
diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp
index d23edcd1d1..f27281866a 100644
--- a/modules/mobile_vr/mobile_vr_interface.cpp
+++ b/modules/mobile_vr/mobile_vr_interface.cpp
@@ -250,6 +250,16 @@ void MobileVRInterface::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversample", PROPERTY_HINT_RANGE, "1.0,2.0,0.1"), "set_oversample", "get_oversample");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "k1", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k1", "get_k1");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "k2", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k2", "get_k2");
+
+ ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &MobileVRInterface::get_vrs_min_radius);
+ ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &MobileVRInterface::set_vrs_min_radius);
+
+ ClassDB::bind_method(D_METHOD("get_vrs_strength"), &MobileVRInterface::get_vrs_strength);
+ ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &MobileVRInterface::set_vrs_strength);
+
+ ADD_GROUP("Vulkan VRS", "vrs_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength");
}
void MobileVRInterface::set_eye_height(const double p_eye_height) {
@@ -316,6 +326,22 @@ double MobileVRInterface::get_k2() const {
return k2;
};
+float MobileVRInterface::get_vrs_min_radius() const {
+ return xr_vrs.get_vrs_min_radius();
+}
+
+void MobileVRInterface::set_vrs_min_radius(float p_vrs_min_radius) {
+ xr_vrs.set_vrs_min_radius(p_vrs_min_radius);
+}
+
+float MobileVRInterface::get_vrs_strength() const {
+ return xr_vrs.get_vrs_strength();
+}
+
+void MobileVRInterface::set_vrs_strength(float p_vrs_strength) {
+ xr_vrs.set_vrs_strength(p_vrs_strength);
+}
+
uint32_t MobileVRInterface::get_view_count() {
// needs stereo...
return 2;
@@ -489,11 +515,16 @@ Vector<BlitToScreen> MobileVRInterface::post_draw_viewport(RID p_render_target,
Vector<BlitToScreen> blit_to_screen;
- // We must have a valid render target
+ // We must have a valid render target.
ERR_FAIL_COND_V(!p_render_target.is_valid(), blit_to_screen);
- // Because we are rendering to our device we must use our main viewport!
- ERR_FAIL_COND_V(p_screen_rect == Rect2(), blit_to_screen);
+ // We will only output to screen if this is our main viewport.
+ if (p_screen_rect == Rect2()) {
+ // Warn the developer once, it's up to the developer to output to screen.
+ WARN_PRINT_ONCE("SubViewport used with MobileVRInterface, no output to screen");
+
+ return blit_to_screen;
+ }
Rect2 modified_screen_rect = Rect2(p_screen_rect.position + offset_rect.position * p_screen_rect.size, p_screen_rect.size * offset_rect.size);
@@ -542,6 +573,23 @@ void MobileVRInterface::process() {
};
};
+RID MobileVRInterface::get_vrs_texture() {
+ PackedVector2Array eye_foci;
+
+ Size2 target_size = get_render_target_size();
+ real_t aspect_ratio = target_size.x / target_size.y;
+ uint32_t view_count = get_view_count();
+
+ for (uint32_t v = 0; v < view_count; v++) {
+ Projection cm = get_projection_for_view(v, aspect_ratio, 0.1, 1000.0);
+ Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0));
+
+ eye_foci.push_back(Vector2(center.x, center.y));
+ }
+
+ return xr_vrs.make_vrs_texture(target_size, eye_foci);
+}
+
MobileVRInterface::MobileVRInterface() {}
MobileVRInterface::~MobileVRInterface() {
diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h
index e1d43fff74..490b1c393c 100644
--- a/modules/mobile_vr/mobile_vr_interface.h
+++ b/modules/mobile_vr/mobile_vr_interface.h
@@ -33,6 +33,7 @@
#include "servers/xr/xr_interface.h"
#include "servers/xr/xr_positional_tracker.h"
+#include "servers/xr/xr_vrs.h"
/**
The mobile interface is a native VR interface that can be used on Android and iOS phones.
@@ -72,6 +73,8 @@ private:
Ref<XRPositionalTracker> head;
Transform3D head_transform;
+ XRVRS xr_vrs;
+
/*
logic for processing our sensor data, this was originally in our positional tracker logic but I think
that doesn't make sense in hindsight. It only makes marginally more sense to park it here for now,
@@ -138,6 +141,12 @@ public:
void set_k2(const double p_k2);
double get_k2() const;
+ float get_vrs_min_radius() const;
+ void set_vrs_min_radius(float p_vrs_min_radius);
+
+ float get_vrs_strength() const;
+ void set_vrs_strength(float p_vrs_strength);
+
virtual StringName get_name() const override;
virtual uint32_t get_capabilities() const override;
@@ -161,6 +170,8 @@ public:
virtual void process() override;
+ virtual RID get_vrs_texture() override;
+
MobileVRInterface();
~MobileVRInterface();
};
diff --git a/modules/mono/.editorconfig b/modules/mono/.editorconfig
index 1e5ae28396..fcd10461ad 100644
--- a/modules/mono/.editorconfig
+++ b/modules/mono/.editorconfig
@@ -1,3 +1,7 @@
+[*.{sln,csproj}]
+end_of_line = crlf
+charset = utf-8-bom
+
[*.sln]
indent_style = tab
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
index 9674626183..2c78645493 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln
@@ -1,5 +1,8 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34728.123
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.NET.Sdk", "Godot.NET.Sdk\Godot.NET.Sdk.csproj", "{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators", "Godot.SourceGenerators\Godot.SourceGenerators.csproj", "{32D31B23-2A45-4099-B4F5-95B4C8FF7D9F}"
@@ -37,4 +40,10 @@ Global
{AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {49831022-16BD-41E0-A5F3-EDE1279F4176}
+ EndGlobalSection
EndGlobal
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
index b396a5b0c7..74623a60ba 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Godot.NET.Sdk.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.Build.NoTargets/2.0.1">
+<Project Sdk="Microsoft.Build.NoTargets/2.0.1">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj
index d0907c1cd4..fc887313d5 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Sample/Godot.SourceGenerators.Sample.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj
index e5a81c0e1c..31a255dcdf 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/Godot.SourceGenerators.Tests.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
index fbabed50d0..1aa2979e76 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Godot.SourceGenerators.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10</LangVersion>
diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj
index fd836f9ad2..f807132509 100644
--- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotTools.BuildLogger.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{6CE9A984-37B1-4F8A-8FE9-609F05F071B3}</ProjectGuid>
<TargetFramework>net6.0</TargetFramework>
diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
index 0755484465..f692f26a8b 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid>
<TargetFramework>net6.0</TargetFramework>
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj
index 3bf678e9f9..0174b25b3f 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/GodotTools.IdeMessaging.CLI.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{B06C2951-C8E3-4F28-80B2-717CF327EB19}</ProjectGuid>
<OutputType>Exe</OutputType>
diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj
index f681228892..2ee28715bf 100644
--- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotTools.IdeMessaging.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{92600954-25F0-4291-8E11-1FEE9FC4BE20}</ProjectGuid>
<TargetFramework>netstandard2.0</TargetFramework>
diff --git a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj
index 09908c85a1..7360118ee4 100644
--- a/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.OpenVisualStudio/GodotTools.OpenVisualStudio.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid>
<OutputType>Exe</OutputType>
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj
index 623475e11a..5547ffcf19 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
<TargetFramework>net6.0</TargetFramework>
diff --git a/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj b/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj
index d60e6343ea..7c19fabaf6 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.Shared/GodotTools.Shared.csproj
@@ -1,8 +1,8 @@
-<Project Sdk="Microsoft.NET.Sdk">
- <PropertyGroup>
- <TargetFramework>net6.0</TargetFramework>
- <!-- Specify compile items manually to avoid including dangling generated items. -->
- <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
- </PropertyGroup>
- <Import Project="GenerateGodotNupkgsVersions.targets" />
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <!-- Specify compile items manually to avoid including dangling generated items. -->
+ <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
+ </PropertyGroup>
+ <Import Project="GenerateGodotNupkgsVersions.targets" />
</Project>
diff --git a/modules/mono/editor/GodotTools/GodotTools.sln b/modules/mono/editor/GodotTools/GodotTools.sln
index 564775635d..1182e2467b 100644
--- a/modules/mono/editor/GodotTools/GodotTools.sln
+++ b/modules/mono/editor/GodotTools/GodotTools.sln
@@ -1,6 +1,8 @@
-
+
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34728.123
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.ProjectEditor", "GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools", "GodotTools\GodotTools.csproj", "{27B00618-A6F2-4828-B922-05CAEB08C286}"
@@ -62,4 +64,10 @@ Global
{55666071-BEC1-4A52-8A98-9A4A7A947DBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55666071-BEC1-4A52-8A98-9A4A7A947DBF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {521EC35A-F7F0-46A9-92CE-680D2F5B02B8}
+ EndGlobalSection
EndGlobal
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index 35b3f5a710..96d2c5c75f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
<TargetFramework>net6.0</TargetFramework>
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index db86693a58..d46160127d 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -4859,7 +4859,7 @@ static void handle_cmdline_options(String glue_dir_path) {
}
static void cleanup_and_exit_godot() {
- // Exit once done
+ // Exit once done.
Main::cleanup(true);
::exit(0);
}
@@ -4878,7 +4878,7 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
elem = elem->next();
} else {
ERR_PRINT(generate_all_glue_option + ": No output directory specified (expected path to '{GODOT_ROOT}/modules/mono/glue').");
- // Exit once done with invalid command line arguments
+ // Exit once done with invalid command line arguments.
cleanup_and_exit_godot();
}
@@ -4889,8 +4889,14 @@ void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args)
}
if (glue_dir_path.length()) {
- handle_cmdline_options(glue_dir_path);
- // Exit once done
+ if (Engine::get_singleton()->is_editor_hint() ||
+ Engine::get_singleton()->is_project_manager_hint()) {
+ handle_cmdline_options(glue_dir_path);
+ } else {
+ // Running from a project folder, which doesn't make sense and crashes.
+ ERR_PRINT(generate_all_glue_option + ": Cannot generate Mono glue while running a game project. Change current directory or enable --editor.");
+ }
+ // Exit once done.
cleanup_and_exit_godot();
}
}
diff --git a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Godot.SourceGenerators.Internal.csproj b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Godot.SourceGenerators.Internal.csproj
index 4d1a5bb76c..81add0e44f 100644
--- a/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Godot.SourceGenerators.Internal.csproj
+++ b/modules/mono/glue/GodotSharp/Godot.SourceGenerators.Internal/Godot.SourceGenerators.Internal.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10</LangVersion>
diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj b/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj
index e58d730ee3..1e60743fb1 100644
--- a/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj
+++ b/modules/mono/glue/GodotSharp/GodotPlugins/GodotPlugins.csproj
@@ -1,18 +1,18 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
- <PropertyGroup>
- <TargetFramework>net6.0</TargetFramework>
- <LangVersion>10</LangVersion>
- <Nullable>enable</Nullable>
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <LangVersion>10</LangVersion>
+ <Nullable>enable</Nullable>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <!-- To generate the .runtimeconfig.json file-->
- <EnableDynamicLoading>true</EnableDynamicLoading>
- <RollForward>LatestMajor</RollForward>
- </PropertyGroup>
+ <!-- To generate the .runtimeconfig.json file-->
+ <EnableDynamicLoading>true</EnableDynamicLoading>
+ <RollForward>LatestMajor</RollForward>
+ </PropertyGroup>
- <ItemGroup>
- <ProjectReference Include="..\GodotSharp\GodotSharp.csproj" />
- </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\GodotSharp\GodotSharp.csproj" />
+ </ItemGroup>
</Project>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp.sln b/modules/mono/glue/GodotSharp/GodotSharp.sln
index 8db42c2d1a..81ff7d7550 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp.sln
+++ b/modules/mono/glue/GodotSharp/GodotSharp.sln
@@ -1,5 +1,8 @@
+
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34728.123
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharp", "GodotSharp\GodotSharp.csproj", "{AEBF0036-DA76-4341-B651-A3F2856AB2FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharpEditor", "GodotSharpEditor\GodotSharpEditor.csproj", "{8FBEC238-D944-4074-8548-B3B524305905}"
@@ -10,8 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.SourceGenerators.Inte
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AEBF0036-DA76-4341-B651-A3F2856AB2FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -31,4 +34,10 @@ Global
{7749662B-E30C-419A-B745-13852573360A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7749662B-E30C-419A-B745-13852573360A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {371B0F03-042D-45FD-A270-F3141F2480CD}
+ EndGlobalSection
EndGlobal
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
index 37f319b697..d8a3e91699 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs
@@ -417,76 +417,31 @@ namespace Godot
}
/// <summary>
- /// Performs a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// Performs a case-sensitive comparison to another string and returns an integer that indicates their relative position in the sort order.
/// </summary>
/// <seealso cref="NocasecmpTo(string, string)"/>
/// <seealso cref="CompareTo(string, string, bool)"/>
/// <param name="instance">The string to compare.</param>
/// <param name="to">The other string to compare.</param>
- /// <returns>-1 if less, 0 if equal and +1 if greater.</returns>
+ /// <returns>An integer that indicates the lexical relationship between the two comparands.</returns>
public static int CasecmpTo(this string instance, string to)
{
return instance.CompareTo(to, caseSensitive: true);
}
/// <summary>
- /// Performs a comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// Performs a comparison to another string and returns an integer that indicates their relative position in the sort order.
/// </summary>
/// <param name="instance">The string to compare.</param>
/// <param name="to">The other string to compare.</param>
/// <param name="caseSensitive">
/// If <see langword="true"/>, the comparison will be case sensitive.
/// </param>
- /// <returns>-1 if less, 0 if equal and +1 if greater.</returns>
+ /// <returns>An integer that indicates the lexical relationship between the two comparands.</returns>
+ [Obsolete("Use string.Compare instead.")]
public static int CompareTo(this string instance, string to, bool caseSensitive = true)
{
- if (string.IsNullOrEmpty(instance))
- return string.IsNullOrEmpty(to) ? 0 : -1;
-
- if (string.IsNullOrEmpty(to))
- return 1;
-
- int instanceIndex = 0;
- int toIndex = 0;
-
- if (caseSensitive) // Outside while loop to avoid checking multiple times, despite some code duplication.
- {
- while (true)
- {
- if (to[toIndex] == 0 && instance[instanceIndex] == 0)
- return 0; // We're equal
- if (instance[instanceIndex] == 0)
- return -1; // If this is empty, and the other one is not, then we're less... I think?
- if (to[toIndex] == 0)
- return 1; // Otherwise the other one is smaller...
- if (instance[instanceIndex] < to[toIndex]) // More than
- return -1;
- if (instance[instanceIndex] > to[toIndex]) // Less than
- return 1;
-
- instanceIndex++;
- toIndex++;
- }
- }
- else
- {
- while (true)
- {
- if (to[toIndex] == 0 && instance[instanceIndex] == 0)
- return 0; // We're equal
- if (instance[instanceIndex] == 0)
- return -1; // If this is empty, and the other one is not, then we're less... I think?
- if (to[toIndex] == 0)
- return 1; // Otherwise the other one is smaller..
- if (char.ToUpperInvariant(instance[instanceIndex]) < char.ToUpperInvariant(to[toIndex])) // More than
- return -1;
- if (char.ToUpperInvariant(instance[instanceIndex]) > char.ToUpperInvariant(to[toIndex])) // Less than
- return 1;
-
- instanceIndex++;
- toIndex++;
- }
- }
+ return string.Compare(instance, to, !caseSensitive);
}
/// <summary>
@@ -1297,13 +1252,13 @@ namespace Godot
}
/// <summary>
- /// Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ /// Performs a case-insensitive comparison to another string and returns an integer that indicates their relative position in the sort order.
/// </summary>
/// <seealso cref="CasecmpTo(string, string)"/>
/// <seealso cref="CompareTo(string, string, bool)"/>
/// <param name="instance">The string to compare.</param>
/// <param name="to">The other string to compare.</param>
- /// <returns>-1 if less, 0 if equal and +1 if greater.</returns>
+ /// <returns>An integer that indicates the lexical relationship between the two comparands.</returns>
public static int NocasecmpTo(this string instance, string to)
{
return instance.CompareTo(to, caseSensitive: false);
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 67282416ed..6b25087c93 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{AEBF0036-DA76-4341-B651-A3F2856AB2FA}</ProjectGuid>
<OutputPath>bin/$(Configuration)</OutputPath>
diff --git a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
index 8373edb9bf..4561fdaf2b 100644
--- a/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharpEditor/GodotSharpEditor.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{8FBEC238-D944-4074-8548-B3B524305905}</ProjectGuid>
<OutputPath>bin/$(Configuration)</OutputPath>
diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml
index 86ba1416c8..309cbe0d72 100644
--- a/modules/openxr/doc_classes/OpenXRInterface.xml
+++ b/modules/openxr/doc_classes/OpenXRInterface.xml
@@ -152,6 +152,14 @@
<member name="render_target_size_multiplier" type="float" setter="set_render_target_size_multiplier" getter="get_render_target_size_multiplier" default="1.0">
The render size multiplier for the current HMD. Must be set before the interface has been initialized.
</member>
+ <member name="vrs_min_radius" type="float" setter="set_vrs_min_radius" getter="get_vrs_min_radius" default="20.0">
+ The minimum radius around the focal point where full quality is guaranteed if VRS is used as a percentage of screen size.
+ [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR].
+ </member>
+ <member name="vrs_strength" type="float" setter="set_vrs_strength" getter="get_vrs_strength" default="1.0">
+ The strength used to calculate the VRS density map. The greater this value, the more noticeable VRS is. This improves performance at the cost of quality.
+ [b]Note:[/b] Mobile and Forward+ renderers only. Requires [member Viewport.vrs_mode] to be set to [constant Viewport.VRS_XR].
+ </member>
</members>
<signals>
<signal name="instance_exiting">
diff --git a/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp b/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp
index 477a1c2609..eea996edd9 100644
--- a/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp
+++ b/modules/openxr/extensions/openxr_eye_gaze_interaction.cpp
@@ -34,6 +34,7 @@
#include "core/os/os.h"
#include "../action_map/openxr_interaction_profile_metadata.h"
+#include "../openxr_api.h"
OpenXREyeGazeInteractionExtension *OpenXREyeGazeInteractionExtension::singleton = nullptr;
@@ -106,3 +107,38 @@ void OpenXREyeGazeInteractionExtension::on_register_metadata() {
metadata->register_interaction_profile("Eye gaze", "/interaction_profiles/ext/eye_gaze_interaction", XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME);
metadata->register_io_path("/interaction_profiles/ext/eye_gaze_interaction", "Gaze pose", "/user/eyes_ext", "/user/eyes_ext/input/gaze_ext/pose", "", OpenXRAction::OPENXR_ACTION_POSE);
}
+
+bool OpenXREyeGazeInteractionExtension::get_eye_gaze_pose(double p_dist, Vector3 &r_eye_pose) {
+ OpenXRAPI *openxr_api = OpenXRAPI::get_singleton();
+ ERR_FAIL_NULL_V(openxr_api, false);
+
+ if (!init_eye_gaze_pose) {
+ init_eye_gaze_pose = true;
+
+ eye_tracker = openxr_api->find_tracker("/user/eyes_ext");
+ if (eye_tracker.is_null()) {
+ WARN_PRINT("Couldn't obtain eye tracker");
+ }
+
+ eye_action = openxr_api->find_action("eye_gaze_pose");
+ if (eye_action.is_null()) {
+ WARN_PRINT("Couldn't obtain pose action for `eye_gaze_pose`, make sure to add this to your action map.");
+ }
+ }
+
+ if (eye_tracker.is_null() || eye_action.is_null()) {
+ return false;
+ }
+
+ Transform3D eye_transform;
+ Vector3 linear_velocity;
+ Vector3 angular_velocity;
+ XRPose::TrackingConfidence confidence = openxr_api->get_action_pose(eye_action, eye_tracker, eye_transform, linear_velocity, angular_velocity);
+ if (confidence == XRPose::XR_TRACKING_CONFIDENCE_NONE) {
+ return false;
+ }
+
+ r_eye_pose = eye_transform.origin + eye_transform.basis[2] * p_dist;
+
+ return true;
+}
diff --git a/modules/openxr/extensions/openxr_eye_gaze_interaction.h b/modules/openxr/extensions/openxr_eye_gaze_interaction.h
index 2b99f8edff..114c1aacc7 100644
--- a/modules/openxr/extensions/openxr_eye_gaze_interaction.h
+++ b/modules/openxr/extensions/openxr_eye_gaze_interaction.h
@@ -50,11 +50,17 @@ public:
virtual void on_register_metadata() override;
+ bool get_eye_gaze_pose(double p_dist, Vector3 &r_eye_pose);
+
private:
static OpenXREyeGazeInteractionExtension *singleton;
bool available = false;
XrSystemEyeGazeInteractionPropertiesEXT properties;
+
+ bool init_eye_gaze_pose = false;
+ RID eye_tracker;
+ RID eye_action;
};
#endif // OPENXR_EYE_GAZE_INTERACTION_H
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 40e3ecfefc..8731a36865 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -54,6 +54,7 @@
#endif
#include "extensions/openxr_composition_layer_depth_extension.h"
+#include "extensions/openxr_eye_gaze_interaction.h"
#include "extensions/openxr_fb_display_refresh_rate_extension.h"
#include "extensions/openxr_fb_foveation_extension.h"
#include "extensions/openxr_fb_update_swapchain_extension.h"
@@ -1826,6 +1827,46 @@ bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z
return graphics_extension->create_projection_fov(render_state.views[p_view].fov, p_z_near, p_z_far, p_camera_matrix);
}
+Vector2 OpenXRAPI::get_eye_focus(uint32_t p_view, float p_aspect) {
+ ERR_FAIL_NULL_V(graphics_extension, Vector2());
+
+ if (!render_state.running) {
+ return Vector2();
+ }
+
+ // xrWaitFrame not run yet
+ if (render_state.predicted_display_time == 0) {
+ return Vector2();
+ }
+
+ // we don't have valid view info
+ if (render_state.views == nullptr || !render_state.view_pose_valid) {
+ return Vector2();
+ }
+
+ Projection cm;
+ if (!graphics_extension->create_projection_fov(render_state.views[p_view].fov, 0.1, 1000.0, cm)) {
+ return Vector2();
+ }
+
+ // Default focus to center...
+ Vector3 focus = cm.xform(Vector3(0.0, 0.0, 999.9));
+
+ // Lets check for eye tracking...
+ OpenXREyeGazeInteractionExtension *eye_gaze_interaction = OpenXREyeGazeInteractionExtension::get_singleton();
+ if (eye_gaze_interaction && eye_gaze_interaction->supports_eye_gaze_interaction()) {
+ Vector3 eye_gaze_pose;
+ if (eye_gaze_interaction->get_eye_gaze_pose(1.0, eye_gaze_pose)) {
+ Transform3D view_transform = transform_from_pose(render_state.views[p_view].pose);
+
+ eye_gaze_pose = view_transform.xform_inv(eye_gaze_pose);
+ focus = cm.xform(eye_gaze_pose);
+ }
+ }
+
+ return Vector2(focus.x, focus.y);
+}
+
bool OpenXRAPI::poll_events() {
ERR_FAIL_COND_V(instance == XR_NULL_HANDLE, false);
@@ -2633,10 +2674,23 @@ bool OpenXRAPI::xr_result(XrResult result, const char *format, Array args) const
RID OpenXRAPI::get_tracker_rid(XrPath p_path) {
List<RID> current;
tracker_owner.get_owned_list(&current);
- for (int i = 0; i < current.size(); i++) {
- Tracker *tracker = tracker_owner.get_or_null(current[i]);
+ for (const RID &E : current) {
+ Tracker *tracker = tracker_owner.get_or_null(E);
if (tracker && tracker->toplevel_path == p_path) {
- return current[i];
+ return E;
+ }
+ }
+
+ return RID();
+}
+
+RID OpenXRAPI::find_tracker(const String &p_name) {
+ List<RID> current;
+ tracker_owner.get_owned_list(&current);
+ for (const RID &E : current) {
+ Tracker *tracker = tracker_owner.get_or_null(E);
+ if (tracker && tracker->name == p_name) {
+ return E;
}
}
@@ -2827,10 +2881,23 @@ void OpenXRAPI::action_set_free(RID p_action_set) {
RID OpenXRAPI::get_action_rid(XrAction p_action) {
List<RID> current;
action_owner.get_owned_list(&current);
- for (int i = 0; i < current.size(); i++) {
- Action *action = action_owner.get_or_null(current[i]);
+ for (const RID &E : current) {
+ Action *action = action_owner.get_or_null(E);
if (action && action->handle == p_action) {
- return current[i];
+ return E;
+ }
+ }
+
+ return RID();
+}
+
+RID OpenXRAPI::find_action(const String &p_name) {
+ List<RID> current;
+ action_owner.get_owned_list(&current);
+ for (const RID &E : current) {
+ Action *action = action_owner.get_or_null(E);
+ if (action && action->name == p_name) {
+ return E;
}
}
@@ -2931,10 +2998,10 @@ void OpenXRAPI::action_free(RID p_action) {
RID OpenXRAPI::get_interaction_profile_rid(XrPath p_path) {
List<RID> current;
interaction_profile_owner.get_owned_list(&current);
- for (int i = 0; i < current.size(); i++) {
- InteractionProfile *ip = interaction_profile_owner.get_or_null(current[i]);
+ for (const RID &E : current) {
+ InteractionProfile *ip = interaction_profile_owner.get_or_null(E);
if (ip && ip->path == p_path) {
- return current[i];
+ return E;
}
}
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index c95867810c..f9d2e60148 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -456,6 +456,7 @@ public:
XRPose::TrackingConfidence get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity);
bool get_view_transform(uint32_t p_view, Transform3D &r_transform);
bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix);
+ Vector2 get_eye_focus(uint32_t p_view, float p_aspect);
bool process();
void pre_render();
@@ -515,6 +516,9 @@ public:
bool interaction_profile_suggest_bindings(RID p_interaction_profile);
void interaction_profile_free(RID p_interaction_profile);
+ RID find_tracker(const String &p_name);
+ RID find_action(const String &p_name);
+
bool sync_action_sets(const Vector<RID> p_active_sets);
bool get_action_bool(RID p_action, RID p_tracker);
float get_action_float(RID p_action, RID p_tracker);
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 39a61d1b4d..b92d1edb90 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -97,6 +97,16 @@ void OpenXRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_hand_interaction_supported"), &OpenXRInterface::is_hand_interaction_supported);
ClassDB::bind_method(D_METHOD("is_eye_gaze_interaction_supported"), &OpenXRInterface::is_eye_gaze_interaction_supported);
+ // VRS
+ ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &OpenXRInterface::get_vrs_min_radius);
+ ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &OpenXRInterface::set_vrs_min_radius);
+ ClassDB::bind_method(D_METHOD("get_vrs_strength"), &OpenXRInterface::get_vrs_strength);
+ ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &OpenXRInterface::set_vrs_strength);
+
+ ADD_GROUP("Vulkan VRS", "vrs_");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength");
+
BIND_ENUM_CONSTANT(HAND_LEFT);
BIND_ENUM_CONSTANT(HAND_RIGHT);
BIND_ENUM_CONSTANT(HAND_MAX);
@@ -872,6 +882,22 @@ Array OpenXRInterface::get_action_sets() const {
return arr;
}
+float OpenXRInterface::get_vrs_min_radius() const {
+ return xr_vrs.get_vrs_min_radius();
+}
+
+void OpenXRInterface::set_vrs_min_radius(float p_vrs_min_radius) {
+ xr_vrs.set_vrs_min_radius(p_vrs_min_radius);
+}
+
+float OpenXRInterface::get_vrs_strength() const {
+ return xr_vrs.get_vrs_strength();
+}
+
+void OpenXRInterface::set_vrs_strength(float p_vrs_strength) {
+ xr_vrs.set_vrs_strength(p_vrs_strength);
+}
+
double OpenXRInterface::get_render_target_size_multiplier() const {
if (openxr_api == nullptr) {
return 1.0;
@@ -1435,6 +1461,24 @@ Vector3 OpenXRInterface::get_hand_joint_angular_velocity(Hand p_hand, HandJoints
return Vector3();
}
+RID OpenXRInterface::get_vrs_texture() {
+ if (!openxr_api) {
+ return RID();
+ }
+
+ PackedVector2Array eye_foci;
+
+ Size2 target_size = get_render_target_size();
+ real_t aspect_ratio = target_size.x / target_size.y;
+ uint32_t view_count = get_view_count();
+
+ for (uint32_t v = 0; v < view_count; v++) {
+ eye_foci.push_back(openxr_api->get_eye_focus(v, aspect_ratio));
+ }
+
+ return xr_vrs.make_vrs_texture(target_size, eye_foci);
+}
+
OpenXRInterface::OpenXRInterface() {
openxr_api = OpenXRAPI::get_singleton();
if (openxr_api) {
diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h
index ac33304757..f0ee0dc3c4 100644
--- a/modules/openxr/openxr_interface.h
+++ b/modules/openxr/openxr_interface.h
@@ -80,6 +80,8 @@ private:
XRPose::TrackingConfidence head_confidence;
Transform3D transform_for_view[2]; // We currently assume 2, but could be 4 for VARJO which we do not support yet
+ XRVRS xr_vrs;
+
void _load_action_map();
struct Action { // An action we've registered with OpenXR
@@ -168,6 +170,12 @@ public:
bool get_foveation_dynamic() const;
void set_foveation_dynamic(bool p_foveation_dynamic);
+ float get_vrs_min_radius() const;
+ void set_vrs_min_radius(float p_vrs_min_radius);
+
+ float get_vrs_strength() const;
+ void set_vrs_strength(float p_vrs_strength);
+
virtual Size2 get_render_target_size() override;
virtual uint32_t get_view_count() override;
virtual Transform3D get_camera_transform() override;
@@ -276,6 +284,8 @@ public:
Vector3 get_hand_joint_linear_velocity(Hand p_hand, HandJoints p_joint) const;
Vector3 get_hand_joint_angular_velocity(Hand p_hand, HandJoints p_joint) const;
+ virtual RID get_vrs_texture() override;
+
OpenXRInterface();
~OpenXRInterface();
};
diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp
index db36a0a630..997e4c931c 100644
--- a/scene/3d/skeleton_3d.cpp
+++ b/scene/3d/skeleton_3d.cpp
@@ -264,6 +264,8 @@ void Skeleton3D::_update_process_order() {
}
}
+ bones_backup.resize(bones.size());
+
process_order_dirty = false;
emit_signal("bone_list_changed");
@@ -271,16 +273,15 @@ void Skeleton3D::_update_process_order() {
#ifndef DISABLE_DEPRECATED
void Skeleton3D::setup_simulator() {
+ if (simulator && simulator->get_parent() == this) {
+ remove_child(simulator);
+ simulator->queue_free();
+ }
PhysicalBoneSimulator3D *sim = memnew(PhysicalBoneSimulator3D);
simulator = sim;
sim->is_compat = true;
sim->set_active(false); // Don't run unneeded process.
- add_child(sim);
-}
-
-void Skeleton3D::remove_simulator() {
- remove_child(simulator);
- memdelete(simulator);
+ add_child(simulator);
}
#endif // _DISABLE_DEPRECATED
@@ -294,11 +295,6 @@ void Skeleton3D::_notification(int p_what) {
setup_simulator();
#endif // _DISABLE_DEPRECATED
} break;
-#ifndef DISABLE_DEPRECATED
- case NOTIFICATION_EXIT_TREE: {
- remove_simulator();
- } break;
-#endif // _DISABLE_DEPRECATED
case NOTIFICATION_UPDATE_SKELETON: {
// Update bone transforms to apply unprocessed poses.
force_update_all_dirty_bones();
@@ -310,19 +306,10 @@ void Skeleton3D::_notification(int p_what) {
// Process modifiers.
_find_modifiers();
- LocalVector<Transform3D> current_bone_poses;
- LocalVector<Vector3> current_pose_positions;
- LocalVector<Quaternion> current_pose_rotations;
- LocalVector<Vector3> current_pose_scales;
- LocalVector<Transform3D> current_bone_global_poses;
if (!modifiers.is_empty()) {
// Store unmodified bone poses.
- for (int i = 0; i < len; i++) {
- current_bone_poses.push_back(bones[i].pose_cache);
- current_pose_positions.push_back(bones[i].pose_position);
- current_pose_rotations.push_back(bones[i].pose_rotation);
- current_pose_scales.push_back(bones[i].pose_scale);
- current_bone_global_poses.push_back(bones[i].global_pose);
+ for (int i = 0; i < bones.size(); i++) {
+ bones_backup[i].save(bones[i]);
}
_process_modifiers();
}
@@ -388,12 +375,8 @@ void Skeleton3D::_notification(int p_what) {
if (!modifiers.is_empty()) {
// Restore unmodified bone poses.
- for (int i = 0; i < len; i++) {
- bonesptr[i].pose_cache = current_bone_poses[i];
- bonesptr[i].pose_position = current_pose_positions[i];
- bonesptr[i].pose_rotation = current_pose_rotations[i];
- bonesptr[i].pose_scale = current_pose_scales[i];
- bonesptr[i].global_pose = current_bone_global_poses[i];
+ for (int i = 0; i < bones.size(); i++) {
+ bones_backup[i].restore(bones.write[i]);
}
}
diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h
index 5b6f60dbd4..23b9423993 100644
--- a/scene/3d/skeleton_3d.h
+++ b/scene/3d/skeleton_3d.h
@@ -69,7 +69,6 @@ class Skeleton3D : public Node3D {
#ifndef DISABLE_DEPRECATED
Node *simulator = nullptr;
void setup_simulator();
- void remove_simulator();
#endif // _DISABLE_DEPRECATED
public:
@@ -88,15 +87,15 @@ private:
struct Bone {
String name;
- int parent;
+ int parent = -1;
Vector<int> child_bones;
Transform3D rest;
Transform3D global_rest;
- bool enabled;
- Transform3D pose_cache;
+ bool enabled = true;
bool pose_cache_dirty = true;
+ Transform3D pose_cache;
Vector3 pose_position;
Quaternion pose_rotation;
Vector3 pose_scale = Vector3(1, 1, 1);
@@ -116,15 +115,29 @@ private:
bool global_pose_override_reset = false;
Transform3D global_pose_override;
#endif // _DISABLE_DEPRECATED
+ };
- Bone() {
- parent = -1;
- child_bones = Vector<int>();
- enabled = true;
-#ifndef DISABLE_DEPRECATED
- global_pose_override_amount = 0;
- global_pose_override_reset = false;
-#endif // _DISABLE_DEPRECATED
+ struct BonePoseBackup {
+ Transform3D pose_cache;
+ Vector3 pose_position;
+ Quaternion pose_rotation;
+ Vector3 pose_scale = Vector3(1, 1, 1);
+ Transform3D global_pose;
+
+ void save(const Bone &p_bone) {
+ pose_cache = p_bone.pose_cache;
+ pose_position = p_bone.pose_position;
+ pose_rotation = p_bone.pose_rotation;
+ pose_scale = p_bone.pose_scale;
+ global_pose = p_bone.global_pose;
+ }
+
+ void restore(Bone &r_bone) {
+ r_bone.pose_cache = pose_cache;
+ r_bone.pose_position = pose_position;
+ r_bone.pose_rotation = pose_rotation;
+ r_bone.pose_scale = pose_scale;
+ r_bone.global_pose = global_pose;
}
};
@@ -156,6 +169,7 @@ private:
void _process_modifiers();
void _process_changed();
void _make_modifiers_dirty();
+ LocalVector<BonePoseBackup> bones_backup;
#ifndef DISABLE_DEPRECATED
void _add_bone_bind_compat_88791(const String &p_name);
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index 89f7ab2391..e0dc300a6b 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -194,6 +194,7 @@ Ref<Material> GeometryInstance3D::get_material_overlay() const {
void GeometryInstance3D::set_transparency(float p_transparency) {
transparency = CLAMP(p_transparency, 0.0f, 1.0f);
RS::get_singleton()->instance_geometry_set_transparency(get_instance(), transparency);
+ update_configuration_warnings();
}
float GeometryInstance3D::get_transparency() const {
@@ -441,6 +442,14 @@ PackedStringArray GeometryInstance3D::get_configuration_warnings() const {
warnings.push_back(RTR("The GeometryInstance3D is configured to fade out smoothly over distance, but the fade transition distance is set to 0.\nTo resolve this, increase Visibility Range End Margin above 0."));
}
+ if (!Math::is_zero_approx(transparency) && OS::get_singleton()->get_current_rendering_method() != "forward_plus") {
+ warnings.push_back(RTR("GeometryInstance3D transparency is only available when using the Forward+ rendering method."));
+ }
+
+ if ((visibility_range_fade_mode == VISIBILITY_RANGE_FADE_SELF || visibility_range_fade_mode == VISIBILITY_RANGE_FADE_DEPENDENCIES) && OS::get_singleton()->get_current_rendering_method() != "forward_plus") {
+ warnings.push_back(RTR("GeometryInstance3D visibility range transparency fade is only available when using the Forward+ rendering method."));
+ }
+
return warnings;
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 9dbe10f30b..06cdc02213 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3735,6 +3735,28 @@ Viewport::VRSMode Viewport::get_vrs_mode() const {
return vrs_mode;
}
+void Viewport::set_vrs_update_mode(VRSUpdateMode p_vrs_update_mode) {
+ ERR_MAIN_THREAD_GUARD;
+
+ vrs_update_mode = p_vrs_update_mode;
+ switch (p_vrs_update_mode) {
+ case VRS_UPDATE_ONCE: {
+ RS::get_singleton()->viewport_set_vrs_update_mode(viewport, RS::VIEWPORT_VRS_UPDATE_ONCE);
+ } break;
+ case VRS_UPDATE_ALWAYS: {
+ RS::get_singleton()->viewport_set_vrs_update_mode(viewport, RS::VIEWPORT_VRS_UPDATE_ALWAYS);
+ } break;
+ default: {
+ RS::get_singleton()->viewport_set_vrs_update_mode(viewport, RS::VIEWPORT_VRS_UPDATE_DISABLED);
+ } break;
+ }
+}
+
+Viewport::VRSUpdateMode Viewport::get_vrs_update_mode() const {
+ ERR_READ_THREAD_GUARD_V(VRS_UPDATE_DISABLED);
+ return vrs_update_mode;
+}
+
void Viewport::set_vrs_texture(Ref<Texture2D> p_texture) {
ERR_MAIN_THREAD_GUARD;
vrs_texture = p_texture;
@@ -4775,6 +4797,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_vrs_mode", "mode"), &Viewport::set_vrs_mode);
ClassDB::bind_method(D_METHOD("get_vrs_mode"), &Viewport::get_vrs_mode);
+ ClassDB::bind_method(D_METHOD("set_vrs_update_mode", "mode"), &Viewport::set_vrs_update_mode);
+ ClassDB::bind_method(D_METHOD("get_vrs_update_mode"), &Viewport::get_vrs_update_mode);
+
ClassDB::bind_method(D_METHOD("set_vrs_texture", "texture"), &Viewport::set_vrs_texture);
ClassDB::bind_method(D_METHOD("get_vrs_texture"), &Viewport::get_vrs_texture);
@@ -4807,6 +4832,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fsr_sharpness", PROPERTY_HINT_RANGE, "0,2,0.1"), "set_fsr_sharpness", "get_fsr_sharpness");
ADD_GROUP("Variable Rate Shading", "vrs_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "vrs_mode", PROPERTY_HINT_ENUM, "Disabled,Texture,Depth buffer,XR"), "set_vrs_mode", "get_vrs_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "vrs_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,Always"), "set_vrs_update_mode", "get_vrs_update_mode");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "vrs_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_vrs_texture", "get_vrs_texture");
#endif
ADD_GROUP("Canvas Items", "canvas_item_");
@@ -4930,12 +4956,21 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(VRS_TEXTURE);
BIND_ENUM_CONSTANT(VRS_XR);
BIND_ENUM_CONSTANT(VRS_MAX);
+
+ BIND_ENUM_CONSTANT(VRS_UPDATE_DISABLED);
+ BIND_ENUM_CONSTANT(VRS_UPDATE_ONCE);
+ BIND_ENUM_CONSTANT(VRS_UPDATE_ALWAYS);
+ BIND_ENUM_CONSTANT(VRS_UPDATE_MAX);
}
void Viewport::_validate_property(PropertyInfo &p_property) const {
if (vrs_mode != VRS_TEXTURE && (p_property.name == "vrs_texture")) {
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
}
+
+ if (vrs_mode == VRS_DISABLED && (p_property.name == "vrs_update_mode")) {
+ p_property.usage = PROPERTY_USAGE_NO_EDITOR;
+ }
}
Viewport::Viewport() {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 394d48143c..2474b890b0 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -213,6 +213,13 @@ public:
VRS_MAX
};
+ enum VRSUpdateMode {
+ VRS_UPDATE_DISABLED,
+ VRS_UPDATE_ONCE,
+ VRS_UPDATE_ALWAYS,
+ VRS_UPDATE_MAX
+ };
+
private:
friend class ViewportTexture;
@@ -337,6 +344,7 @@ private:
// VRS
VRSMode vrs_mode = VRS_DISABLED;
+ VRSUpdateMode vrs_update_mode = VRS_UPDATE_ONCE;
Ref<Texture2D> vrs_texture;
struct GUI {
@@ -636,6 +644,9 @@ public:
void set_vrs_mode(VRSMode p_vrs_mode);
VRSMode get_vrs_mode() const;
+ void set_vrs_update_mode(VRSUpdateMode p_vrs_update_mode);
+ VRSUpdateMode get_vrs_update_mode() const;
+
void set_vrs_texture(Ref<Texture2D> p_texture);
Ref<Texture2D> get_vrs_texture() const;
@@ -844,6 +855,7 @@ VARIANT_ENUM_CAST(Viewport::DebugDraw);
VARIANT_ENUM_CAST(Viewport::SDFScale);
VARIANT_ENUM_CAST(Viewport::SDFOversize);
VARIANT_ENUM_CAST(Viewport::VRSMode);
+VARIANT_ENUM_CAST(Viewport::VRSUpdateMode);
VARIANT_ENUM_CAST(SubViewport::ClearMode);
VARIANT_ENUM_CAST(Viewport::RenderInfo);
VARIANT_ENUM_CAST(Viewport::RenderInfoType);
diff --git a/scene/resources/syntax_highlighter.cpp b/scene/resources/syntax_highlighter.cpp
index c735395829..6da4215031 100644
--- a/scene/resources/syntax_highlighter.cpp
+++ b/scene/resources/syntax_highlighter.cpp
@@ -303,7 +303,7 @@ Dictionary CodeHighlighter::_get_line_syntax_highlighting_impl(int p_line) {
}
// Check for dot or underscore or 'x' for hex notation in floating point number or 'e' for scientific notation.
- if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'f' || str[j] == 'e') && !in_word && prev_is_number && !is_number) {
+ if ((str[j] == '.' || str[j] == 'x' || str[j] == '_' || str[j] == 'f' || str[j] == 'e' || (uint_suffix_enabled && str[j] == 'u')) && !in_word && prev_is_number && !is_number) {
is_number = true;
is_a_symbol = false;
is_char = false;
@@ -617,6 +617,10 @@ void CodeHighlighter::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "color_regions"), "set_color_regions", "get_color_regions");
}
+void CodeHighlighter::set_uint_suffix_enabled(bool p_enabled) {
+ uint_suffix_enabled = p_enabled;
+}
+
void CodeHighlighter::set_number_color(Color p_color) {
number_color = p_color;
clear_highlighting_cache();
diff --git a/scene/resources/syntax_highlighter.h b/scene/resources/syntax_highlighter.h
index cac2807ee2..bc66f434d4 100644
--- a/scene/resources/syntax_highlighter.h
+++ b/scene/resources/syntax_highlighter.h
@@ -93,6 +93,8 @@ private:
Color symbol_color;
Color number_color;
+ bool uint_suffix_enabled = false;
+
protected:
static void _bind_methods();
@@ -139,6 +141,8 @@ public:
void set_member_variable_color(Color p_color);
Color get_member_variable_color() const;
+
+ void set_uint_suffix_enabled(bool p_enabled = true);
};
#endif // SYNTAX_HIGHLIGHTER_H
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 1a75614a4c..7a15d202a3 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -325,6 +325,7 @@ void register_server_types() {
PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D");
GDREGISTER_ABSTRACT_CLASS(XRInterface);
+ GDREGISTER_CLASS(XRVRS);
GDREGISTER_CLASS(XRBodyTracker);
GDREGISTER_CLASS(XRControllerTracker);
GDREGISTER_CLASS(XRFaceTracker);
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 1331ca72c2..43572b65e0 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -193,6 +193,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {}
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; }
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override {}
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_UPDATE_DISABLED; }
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
index 30c318fb9a..94453bf95f 100644
--- a/servers/rendering/renderer_rd/effects/vrs.cpp
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -80,7 +80,16 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
- VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+ VRSPushConstant push_constant = {};
+
+ int mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+
+ // Set maximum texel factor based on maximum fragment size, some GPUs do not support 8x8 (fragment shading rate approach).
+ if (MIN(RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_WIDTH), RD::get_singleton()->limit_get(RD::LIMIT_VRS_MAX_FRAGMENT_HEIGHT)) > 4) {
+ push_constant.max_texel_factor = 3.0;
+ } else {
+ push_constant.max_texel_factor = 2.0;
+ }
RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -88,7 +97,7 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>());
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
- // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant));
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(VRSPushConstant));
RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u);
RD::get_singleton()->draw_list_end();
}
@@ -111,12 +120,11 @@ Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
TextureStorage *texture_storage = TextureStorage::get_singleton();
RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
+ RS::ViewportVRSUpdateMode vrs_update_mode = texture_storage->render_target_get_vrs_update_mode(p_render_target);
- if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ if (vrs_mode != RS::VIEWPORT_VRS_DISABLED && vrs_update_mode != RS::VIEWPORT_VRS_UPDATE_DISABLED) {
RD::get_singleton()->draw_command_begin_label("VRS Setup");
- // TODO figure out if image has changed since it was last copied so we can save some resources..
-
if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) {
RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target);
if (vrs_texture.is_valid()) {
@@ -145,6 +153,10 @@ void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
#endif // _3D_DISABLED
}
+ if (vrs_update_mode == RS::VIEWPORT_VRS_UPDATE_ONCE) {
+ texture_storage->render_target_set_vrs_update_mode(p_render_target, RS::VIEWPORT_VRS_UPDATE_DISABLED);
+ }
+
RD::get_singleton()->draw_command_end_label();
}
}
diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h
index b18cf55791..94878e4661 100644
--- a/servers/rendering/renderer_rd/effects/vrs.h
+++ b/servers/rendering/renderer_rd/effects/vrs.h
@@ -47,11 +47,12 @@ private:
VRS_MAX,
};
- /* we have no push constant here (yet)
struct VRSPushConstant {
-
+ float max_texel_factor; // 4x8, 8x4 and 8x8 are only available on some GPUs.
+ float res1;
+ float res2;
+ float res3;
};
- */
struct VRSShader {
// VRSPushConstant push_constant;
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
index 23b0373eef..7ed3fa3348 100644
--- a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -19,6 +19,14 @@ layout(location = 0) out vec3 uv_interp;
layout(location = 0) out vec2 uv_interp;
#endif
+layout(push_constant, std430) uniform Params {
+ float max_texel_factor;
+ float res1;
+ float res2;
+ float res3;
+}
+params;
+
void main() {
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0);
@@ -53,6 +61,14 @@ layout(set = 0, binding = 0) uniform sampler2D source_color;
layout(location = 0) out uint frag_color;
+layout(push_constant, std430) uniform Params {
+ float max_texel_factor;
+ float res1;
+ float res2;
+ float res3;
+}
+params;
+
void main() {
#ifdef USE_MULTIVIEW
vec3 uv = uv_interp;
@@ -60,20 +76,22 @@ void main() {
vec2 uv = uv_interp;
#endif
-#ifdef USE_MULTIVIEW
+ // Input is standardised. R for X, G for Y, 0.0 (0) = 1, 0.33 (85) = 2, 0.66 (170) = 3, 1.0 (255) = 8
vec4 color = textureLod(source_color, uv, 0.0);
- frag_color = uint(color.r * 255.0);
-#else /* USE_MULTIVIEW */
- vec4 color = textureLod(source_color, uv, 0.0);
-
- // for user supplied VRS map we do a color mapping
- color.r *= 3.0;
- frag_color = int(color.r) << 2;
- color.g *= 3.0;
- frag_color += int(color.g);
-
- // note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported
- // 4x8, 8x4 and 8x8 are only available on some GPUs
-#endif /* USE_MULTIVIEW */
+ // Output image shading rate image for VRS according to VK_KHR_fragment_shading_rate.
+ color.r = clamp(floor(color.r * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
+ color.g = clamp(floor(color.g * params.max_texel_factor + 0.1), 0.0, params.max_texel_factor);
+
+ // Note 1x4, 4x1, 1x8, 8x1, 2x8 and 8x2 are not supported:
+ if (color.r < (color.g - 1.0)) {
+ color.r = color.g - 1.0;
+ }
+ if (color.g < (color.r - 1.0)) {
+ color.g = color.r - 1.0;
+ }
+
+ // Encode to frag_color;
+ frag_color = int(color.r + 0.1) << 2;
+ frag_color += int(color.g + 0.1);
}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 76ff566b18..f844919df1 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -3960,6 +3960,20 @@ RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_targ
return rt->vrs_mode;
}
+void TextureStorage::render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_NULL(rt);
+
+ rt->vrs_update_mode = p_mode;
+}
+
+RS::ViewportVRSUpdateMode TextureStorage::render_target_get_vrs_update_mode(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_NULL_V(rt, RS::VIEWPORT_VRS_UPDATE_DISABLED);
+
+ return rt->vrs_update_mode;
+}
+
void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL(rt);
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 1304b284d5..704f5fb1bd 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -366,6 +366,7 @@ private:
// VRS
RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
+ RS::ViewportVRSUpdateMode vrs_update_mode = RS::VIEWPORT_VRS_UPDATE_ONCE;
RID vrs_texture;
// overridden textures
@@ -746,6 +747,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override;
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) override;
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const override;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
virtual RID render_target_get_vrs_texture(RID p_render_target) const override;
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 31d5a9074c..075df10e05 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -1450,6 +1450,13 @@ void RendererViewport::viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode
_configure_3d_render_buffers(viewport);
}
+void RendererViewport::viewport_set_vrs_update_mode(RID p_viewport, RS::ViewportVRSUpdateMode p_mode) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_NULL(viewport);
+
+ RSG::texture_storage->render_target_set_vrs_update_mode(viewport->render_target, p_mode);
+}
+
void RendererViewport::viewport_set_vrs_texture(RID p_viewport, RID p_texture) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_NULL(viewport);
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 5107398c54..8bdce04c50 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -298,6 +298,7 @@ public:
virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const;
void viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode);
+ void viewport_set_vrs_update_mode(RID p_viewport, RS::ViewportVRSUpdateMode p_mode);
void viewport_set_vrs_texture(RID p_viewport, RID p_texture);
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index e46f08c7b0..1ee5362f2c 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -3858,6 +3858,8 @@ void RenderingDevice::draw_list_draw(DrawListID p_list, bool p_use_indices, uint
draw_graph.add_draw_list_draw(to_draw, p_instances);
}
+
+ dl->state.draw_count++;
}
void RenderingDevice::draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) {
@@ -4201,6 +4203,7 @@ void RenderingDevice::compute_list_dispatch(ComputeListID p_list, uint32_t p_x_g
}
draw_graph.add_compute_list_dispatch(p_x_groups, p_y_groups, p_z_groups);
+ cl->state.dispatch_count++;
}
void RenderingDevice::compute_list_dispatch_threads(ComputeListID p_list, uint32_t p_x_threads, uint32_t p_y_threads, uint32_t p_z_threads) {
@@ -4294,6 +4297,7 @@ void RenderingDevice::compute_list_dispatch_indirect(ComputeListID p_list, RID p
}
draw_graph.add_compute_list_dispatch_indirect(buffer->driver_id, p_offset);
+ cl->state.dispatch_count++;
if (buffer->draw_tracker != nullptr) {
draw_graph.add_compute_list_usage(buffer->draw_tracker, RDG::RESOURCE_USAGE_INDIRECT_BUFFER_READ);
@@ -5206,8 +5210,8 @@ void RenderingDevice::_free_rids(T &p_owner, const char *p_type) {
}
void RenderingDevice::capture_timestamp(const String &p_name) {
- ERR_FAIL_COND_MSG(draw_list != nullptr, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name);
- ERR_FAIL_COND_MSG(compute_list != nullptr, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name);
+ ERR_FAIL_COND_MSG(draw_list != nullptr && draw_list->state.draw_count > 0, "Capturing timestamps during draw list creation is not allowed. Offending timestamp was: " + p_name);
+ ERR_FAIL_COND_MSG(compute_list != nullptr && compute_list->state.dispatch_count > 0, "Capturing timestamps during compute list creation is not allowed. Offending timestamp was: " + p_name);
ERR_FAIL_COND(frames[frame].timestamp_count >= max_timestamp_query_elements);
draw_graph.add_capture_timestamp(frames[frame].timestamp_pool, frames[frame].timestamp_count);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 9a898a2fca..9db2fdfbf4 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -1046,6 +1046,7 @@ private:
uint32_t pipeline_shader_layout_hash = 0;
RID vertex_array;
RID index_array;
+ uint32_t draw_count = 0;
} state;
#ifdef DEBUG_ENABLED
@@ -1147,6 +1148,7 @@ private:
uint32_t local_group_size[3] = { 0, 0, 0 };
uint8_t push_constant_data[MAX_PUSH_CONSTANT_SIZE] = {};
uint32_t push_constant_size = 0;
+ uint32_t dispatch_count = 0;
} state;
#ifdef DEBUG_ENABLED
diff --git a/servers/rendering/rendering_device_commons.h b/servers/rendering/rendering_device_commons.h
index 28d641c879..918bf9b834 100644
--- a/servers/rendering/rendering_device_commons.h
+++ b/servers/rendering/rendering_device_commons.h
@@ -810,6 +810,8 @@ public:
LIMIT_SUBGROUP_OPERATIONS,
LIMIT_VRS_TEXEL_WIDTH,
LIMIT_VRS_TEXEL_HEIGHT,
+ LIMIT_VRS_MAX_FRAGMENT_WIDTH,
+ LIMIT_VRS_MAX_FRAGMENT_HEIGHT,
};
enum Features {
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index e0049e3fa4..bb2f3d94ce 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -672,6 +672,7 @@ public:
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode)
+ FUNC2(viewport_set_vrs_update_mode, RID, ViewportVRSUpdateMode)
FUNC2(viewport_set_vrs_texture, RID, RID)
/* COMPOSITOR EFFECT */
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index cf37fbfb4a..72c4dd305b 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -169,6 +169,8 @@ public:
virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0;
virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const = 0;
+ virtual void render_target_set_vrs_update_mode(RID p_render_target, RS::ViewportVRSUpdateMode p_mode) = 0;
+ virtual RS::ViewportVRSUpdateMode render_target_get_vrs_update_mode(RID p_render_target) const = 0;
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0;
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 60e8f18c19..ab82e42f43 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -2824,6 +2824,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
ClassDB::bind_method(D_METHOD("viewport_set_vrs_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_mode);
+ ClassDB::bind_method(D_METHOD("viewport_set_vrs_update_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_vrs_texture", "viewport", "texture"), &RenderingServer::viewport_set_vrs_texture);
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR);
@@ -2832,7 +2833,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED);
- BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled); must be manually updated.
+ BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); // Then goes to disabled, must be manually updated.
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); // Default
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS);
@@ -2914,6 +2915,11 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_VRS_XR);
BIND_ENUM_CONSTANT(VIEWPORT_VRS_MAX);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_ONCE); // Then goes to disabled, must be manually updated.
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_ALWAYS);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_UPDATE_MAX);
+
/* SKY API */
ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 240d82c90b..5bc028dfdd 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -1056,7 +1056,15 @@ public:
VIEWPORT_VRS_MAX,
};
+ enum ViewportVRSUpdateMode {
+ VIEWPORT_VRS_UPDATE_DISABLED,
+ VIEWPORT_VRS_UPDATE_ONCE,
+ VIEWPORT_VRS_UPDATE_ALWAYS,
+ VIEWPORT_VRS_UPDATE_MAX,
+ };
+
virtual void viewport_set_vrs_mode(RID p_viewport, ViewportVRSMode p_mode) = 0;
+ virtual void viewport_set_vrs_update_mode(RID p_viewport, ViewportVRSUpdateMode p_mode) = 0;
virtual void viewport_set_vrs_texture(RID p_viewport, RID p_texture) = 0;
/* SKY API */
@@ -1815,6 +1823,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode);
+VARIANT_ENUM_CAST(RenderingServer::ViewportVRSUpdateMode);
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
VARIANT_ENUM_CAST(RenderingServer::CompositorEffectCallbackType);
VARIANT_ENUM_CAST(RenderingServer::CompositorEffectFlags);
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 9ced28fd52..26f315a454 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -132,13 +132,7 @@ void XRInterface::set_primary(bool p_primary) {
XRInterface::XRInterface() {}
-XRInterface::~XRInterface() {
- if (vrs.vrs_texture.is_valid()) {
- ERR_FAIL_NULL(RenderingServer::get_singleton());
- RS::get_singleton()->free(vrs.vrs_texture);
- vrs.vrs_texture = RID();
- }
-}
+XRInterface::~XRInterface() {}
// query if this interface supports this play area mode
bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
@@ -176,80 +170,7 @@ int XRInterface::get_camera_feed_id() {
}
RID XRInterface::get_vrs_texture() {
- // Default logic will return a standard VRS image based on our target size and default projections.
- // Note that this only gets called if VRS is supported on the hardware.
-
- int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
- int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
- int view_count = get_view_count();
- Size2 target_size = get_render_target_size();
- real_t aspect = target_size.x / target_size.y; // is this y/x ?
- Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_width), round(0.5 + target_size.y / texel_height));
- real_t radius = vrs_size.length() * 0.5;
- Size2 vrs_sizei = vrs_size;
-
- if (vrs.size != vrs_sizei) {
- const uint8_t densities[] = {
- 0, // 1x1
- 1, // 1x2
- // 2, // 1x4 - not supported
- // 3, // 1x8 - not supported
- // 4, // 2x1
- 5, // 2x2
- 6, // 2x4
- // 9, // 4x2
- 10, // 4x4
- };
-
- // out with the old
- if (vrs.vrs_texture.is_valid()) {
- RS::get_singleton()->free(vrs.vrs_texture);
- vrs.vrs_texture = RID();
- }
-
- // in with the new
- Vector<Ref<Image>> images;
- vrs.size = vrs_sizei;
-
- for (int i = 0; i < view_count && i < 2; i++) {
- PackedByteArray data;
- data.resize(vrs_sizei.x * vrs_sizei.y);
- uint8_t *data_ptr = data.ptrw();
-
- // Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result...
- Projection cm = get_projection_for_view(i, aspect, 0.1, 1000.0);
- Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0));
-
- Vector2i view_center;
- view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5);
- view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5);
-
- int d = 0;
- for (int y = 0; y < vrs_sizei.y; y++) {
- for (int x = 0; x < vrs_sizei.x; x++) {
- Vector2 offset = Vector2(x - view_center.x, y - view_center.y);
- offset.y *= aspect;
- real_t distance = offset.length();
- int idx = round(5.0 * distance / radius);
- if (idx > 4) {
- idx = 4;
- }
- uint8_t density = densities[idx];
-
- data_ptr[d++] = density;
- }
- }
- images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data));
- }
-
- if (images.size() == 1) {
- vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
- } else {
- vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
- }
- }
-
- return vrs.vrs_texture;
+ return RID();
}
/** these are optional, so we want dummies **/
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 809800d8b9..7beec219bb 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -34,6 +34,7 @@
#include "core/math/projection.h"
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
+#include "xr_vrs.h"
// forward declaration
struct BlitToScreen;
@@ -133,7 +134,6 @@ public:
// These methods are called from the rendering thread.
virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */
virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */
- virtual RID get_vrs_texture(); /* obtain VRS texture */
virtual RID get_color_texture(); /* obtain color output texture (if applicable) */
virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */
virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */
@@ -149,19 +149,16 @@ public:
virtual bool start_passthrough() { return false; }
virtual void stop_passthrough() {}
- /** environment blend mode. */
+ /** environment blend mode **/
virtual Array get_supported_environment_blend_modes();
virtual XRInterface::EnvironmentBlendMode get_environment_blend_mode() const { return XR_ENV_BLEND_MODE_OPAQUE; }
virtual bool set_environment_blend_mode(EnvironmentBlendMode mode) { return false; }
+ /** VRS **/
+ virtual RID get_vrs_texture(); /* obtain VRS texture */
+
XRInterface();
~XRInterface();
-
-private:
- struct VRSData {
- RID vrs_texture;
- Size2i size;
- } vrs;
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
diff --git a/servers/xr/xr_vrs.cpp b/servers/xr/xr_vrs.cpp
new file mode 100644
index 0000000000..9d1e2f2068
--- /dev/null
+++ b/servers/xr/xr_vrs.cpp
@@ -0,0 +1,151 @@
+/**************************************************************************/
+/* xr_vrs.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "xr_vrs.h"
+
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering_server.h"
+
+void XRVRS::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_vrs_min_radius"), &XRVRS::get_vrs_min_radius);
+ ClassDB::bind_method(D_METHOD("set_vrs_min_radius", "radius"), &XRVRS::set_vrs_min_radius);
+
+ ClassDB::bind_method(D_METHOD("get_vrs_strength"), &XRVRS::get_vrs_strength);
+ ClassDB::bind_method(D_METHOD("set_vrs_strength", "strength"), &XRVRS::set_vrs_strength);
+
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_min_radius", PROPERTY_HINT_RANGE, "1.0,100.0,1.0"), "set_vrs_min_radius", "get_vrs_min_radius");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "vrs_strength", PROPERTY_HINT_RANGE, "0.1,10.0,0.1"), "set_vrs_strength", "get_vrs_strength");
+
+ ClassDB::bind_method(D_METHOD("make_vrs_texture", "target_size", "eye_foci"), &XRVRS::make_vrs_texture);
+}
+
+XRVRS::~XRVRS() {
+ if (vrs_texture.is_valid()) {
+ ERR_FAIL_NULL(RS::get_singleton());
+ RS::get_singleton()->free(vrs_texture);
+ vrs_texture = RID();
+ }
+}
+
+float XRVRS::get_vrs_min_radius() const {
+ return vrs_min_radius;
+}
+
+void XRVRS::set_vrs_min_radius(float p_vrs_min_radius) {
+ if (p_vrs_min_radius < 1.0) {
+ WARN_PRINT_ONCE("VRS minimum radius can not be set below 1.0");
+ vrs_min_radius = 1.0;
+ } else if (p_vrs_min_radius > 100.0) {
+ WARN_PRINT_ONCE("VRS minimum radius can not be set above 100.0");
+ vrs_min_radius = 100.0;
+ } else {
+ vrs_min_radius = p_vrs_min_radius;
+ vrs_dirty = true;
+ }
+}
+
+float XRVRS::get_vrs_strength() const {
+ return vrs_strength;
+}
+
+void XRVRS::set_vrs_strength(float p_vrs_strength) {
+ if (p_vrs_strength < 0.1) {
+ WARN_PRINT_ONCE("VRS strength can not be set below 0.1");
+ vrs_strength = 0.1;
+ } else if (p_vrs_strength > 10.0) {
+ WARN_PRINT_ONCE("VRS strength can not be set above 10.0");
+ vrs_strength = 10.0;
+ } else {
+ vrs_strength = p_vrs_strength;
+ vrs_dirty = true;
+ }
+}
+
+RID XRVRS::make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci) {
+ ERR_FAIL_COND_V(p_eye_foci.is_empty(), RID());
+
+ int32_t texel_width = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_WIDTH);
+ int32_t texel_height = RD::get_singleton()->limit_get(RD::LIMIT_VRS_TEXEL_HEIGHT);
+
+ Size2 vrs_size = Size2(0.5 + p_target_size.x / texel_width, 0.5 + p_target_size.y / texel_height).round();
+ float max_radius = 0.5 * MIN(vrs_size.x, vrs_size.y); // Maximum radius that fits inside of our image
+ float min_radius = vrs_min_radius * max_radius / 100.0; // Minimum radius as a percentage of our size
+ real_t outer_radius = MAX(1.0, (max_radius - min_radius) / vrs_strength);
+ Size2 vrs_sizei = vrs_size;
+
+ // Our density map is now unified, with a value of (0.0, 0.0) meaning a 1x1 texel size and (1.0, 1.0) an max texel size.
+ // For our standard VRS extension on Vulkan this means a maximum of 8x8.
+ // For the density map extension this scales depending on the max texel size.
+
+ if (target_size != vrs_sizei || eye_foci != p_eye_foci || vrs_dirty) {
+ // Out with the old.
+ if (vrs_texture.is_valid()) {
+ RS::get_singleton()->free(vrs_texture);
+ vrs_texture = RID();
+ }
+
+ // In with the new.
+ Vector<Ref<Image>> images;
+ target_size = vrs_sizei;
+ eye_foci = p_eye_foci;
+
+ for (int i = 0; i < eye_foci.size() && i < RendererSceneRender::MAX_RENDER_VIEWS; i++) {
+ PackedByteArray data;
+ data.resize(vrs_sizei.x * vrs_sizei.y * 2);
+ uint8_t *data_ptr = data.ptrw();
+
+ Vector2i view_center;
+ view_center.x = int(vrs_size.x * (eye_foci[i].x + 1.0) * 0.5);
+ view_center.y = int(vrs_size.y * (eye_foci[i].y + 1.0) * 0.5);
+
+ int d = 0;
+ for (int y = 0; y < vrs_sizei.y; y++) {
+ for (int x = 0; x < vrs_sizei.x; x++) {
+ Vector2 offset = Vector2(x - view_center.x, y - view_center.y);
+ real_t density = 255.0 * MAX(0.0, (Math::abs(offset.x) - min_radius) / outer_radius);
+ data_ptr[d++] = MIN(255, density);
+ density = 255.0 * MAX(0.0, (Math::abs(offset.y) - min_radius) / outer_radius);
+ data_ptr[d++] = MIN(255, density);
+ }
+ }
+ images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_RG8, data));
+ }
+
+ if (images.size() == 1) {
+ vrs_texture = RS::get_singleton()->texture_2d_create(images[0]);
+ } else {
+ vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY);
+ }
+
+ vrs_dirty = false;
+ }
+
+ return vrs_texture;
+}
diff --git a/servers/xr/xr_vrs.h b/servers/xr/xr_vrs.h
new file mode 100644
index 0000000000..35dfe55620
--- /dev/null
+++ b/servers/xr/xr_vrs.h
@@ -0,0 +1,67 @@
+/**************************************************************************/
+/* xr_vrs.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef XR_VRS_H
+#define XR_VRS_H
+
+#include "core/object/class_db.h"
+#include "core/object/object.h"
+#include "core/templates/rid.h"
+#include "core/variant/variant.h"
+
+/* This is a helper class for generating stereoscopic VRS images */
+
+class XRVRS : public Object {
+ GDCLASS(XRVRS, Object);
+
+private:
+ float vrs_min_radius = 20.0;
+ float vrs_strength = 1.0;
+ bool vrs_dirty = true;
+
+ RID vrs_texture;
+ Size2i target_size;
+ PackedVector2Array eye_foci;
+
+protected:
+ static void _bind_methods();
+
+public:
+ ~XRVRS();
+
+ float get_vrs_min_radius() const;
+ void set_vrs_min_radius(float p_vrs_min_radius);
+ float get_vrs_strength() const;
+ void set_vrs_strength(float p_vrs_strength);
+
+ RID make_vrs_texture(const Size2 &p_target_size, const PackedVector2Array &p_eye_foci);
+};
+
+#endif // XR_VRS_H