diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 14bbe635a4f0..28eeb2ebb3c7 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -2481,7 +2481,7 @@ Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
return rt->size;
}
-void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) {
+void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL(rt);
ERR_FAIL_COND(rt->direct_to_screen);
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index 916662dcd66f..1fecb2e5bb39 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -685,13 +685,17 @@ class TextureStorage : public RendererTextureStorage {
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(); }
- virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override;
virtual RID render_target_get_override_color(RID p_render_target) const override;
virtual RID render_target_get_override_depth(RID p_render_target) const override;
virtual RID render_target_get_override_velocity(RID p_render_target) const override;
+ virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); }
virtual RID render_target_get_texture(RID p_render_target) override;
+ virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
+ virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(); }
+
void bind_framebuffer(GLuint framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}
diff --git a/modules/openxr/doc_classes/OpenXRAPIExtension.xml b/modules/openxr/doc_classes/OpenXRAPIExtension.xml
index 432b331eecd2..d244b4219d10 100644
--- a/modules/openxr/doc_classes/OpenXRAPIExtension.xml
+++ b/modules/openxr/doc_classes/OpenXRAPIExtension.xml
@@ -82,12 +82,32 @@
Returns the predicted display timing for the current frame.
+
+
+
+ Returns the far boundary value of the camera frustum.
+ [b]Note:[/b] This is only accessible in the render thread.
+
+
+
+
+
+ Returns the near boundary value of the camera frustum.
+ [b]Note:[/b] This is only accessible in the render thread.
+
+
Returns the OpenXR session, which is an [url=https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSession.html]XrSession[/url] cast to an integer.
+
+
+
+ Returns an array of supported swapchain formats.
+
+
@@ -133,6 +153,54 @@
Returns [code]true[/code] if OpenXR is enabled.
+
+
+
+
+ Acquires the image of the provided swapchain.
+
+
+
+
+
+
+
+
+
+
+
+
+ Returns a pointer to a new swapchain created using the provided parameters.
+
+
+
+
+
+
+ Destroys the provided swapchain and frees it from memory.
+
+
+
+
+
+
+ Returns the RID of the provided swapchain's image.
+
+
+
+
+
+
+ Returns the [code]XrSwapchain[/code] handle of the provided swapchain.
+
+
+
+
+
+
+ Releases the image of the provided swapchain.
+
+
@@ -140,6 +208,13 @@
Registers the given extension as a composition layer provider.
+
+
+
+
+ Registers the given extension as a provider of additional data structures to projections views.
+
+
@@ -156,6 +231,27 @@
Set the object name of an OpenXR object, used for debug output. [param object_type] must be a valid OpenXR [code]XrObjectType[/code] enum and [param object_handle] must be a valid OpenXR object handle.
+
+
+
+
+ Sets the render target of the velocity depth texture.
+
+
+
+
+
+
+ Sets the target size of the velocity and velocity depth textures.
+
+
+
+
+
+
+ Sets the render target of the velocity texture.
+
+
@@ -170,6 +266,13 @@
Unregisters the given extension as a composition layer provider.
+
+
+
+
+ Unregisters the given extension as a provider of additional data structures to projections views.
+
+
diff --git a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
index c174ee4d69cc..cf6cd37c3084 100644
--- a/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
+++ b/modules/openxr/doc_classes/OpenXRExtensionWrapperExtension.xml
@@ -217,6 +217,14 @@
Adds additional data structures when the OpenXR instance is created.
+
+
+
+
+
+ Adds additional data structures to the projection view of the given [param view_index].
+
+
diff --git a/modules/openxr/extensions/openxr_composition_layer_extension.cpp b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
index 1e3490d1ed9c..f6270288913a 100644
--- a/modules/openxr/extensions/openxr_composition_layer_extension.cpp
+++ b/modules/openxr/extensions/openxr_composition_layer_extension.cpp
@@ -210,7 +210,7 @@ void OpenXRViewportCompositionLayerProvider::set_viewport(RID p_viewport, Size2i
if (subviewport.viewport != p_viewport) {
if (subviewport.viewport.is_valid()) {
RID rt = rs->viewport_get_render_target(subviewport.viewport);
- RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID());
+ RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID(), RID());
}
subviewport.viewport = p_viewport;
@@ -323,7 +323,7 @@ void OpenXRViewportCompositionLayerProvider::on_pre_render() {
if (update_and_acquire_swapchain(update_mode == RS::VIEWPORT_UPDATE_ONCE)) {
// Render to our XR swapchain image.
RID rt = rs->viewport_get_render_target(subviewport.viewport);
- RSG::texture_storage->render_target_set_override(rt, get_current_swapchain_texture(), RID(), RID());
+ RSG::texture_storage->render_target_set_override(rt, get_current_swapchain_texture(), RID(), RID(), RID());
}
}
}
diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h
index 95b537d1b453..9e3a7136f56b 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper.h
@@ -62,6 +62,7 @@ class OpenXRExtensionWrapper {
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; } // Add additional data structures when we create our OpenXR session.
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) { return p_next_pointer; } // Add additional data structures when creating OpenXR swap chains.
virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) { return p_next_pointer; }
+ virtual void *set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) { return p_next_pointer; }
virtual PackedStringArray get_suggested_tracker_names() { return PackedStringArray(); }
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
index fb8d1b9d69e0..e6a4c2618c68 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.cpp
@@ -39,6 +39,7 @@ void OpenXRExtensionWrapperExtension::_bind_methods() {
GDVIRTUAL_BIND(_set_session_create_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_swapchain_create_info_and_get_next_pointer, "next_pointer");
GDVIRTUAL_BIND(_set_hand_joint_locations_and_get_next_pointer, "hand_index", "next_pointer");
+ GDVIRTUAL_BIND(_set_projection_views_and_get_next_pointer, "view_index", "next_pointer");
GDVIRTUAL_BIND(_get_composition_layer_count);
GDVIRTUAL_BIND(_get_composition_layer, "index");
GDVIRTUAL_BIND(_get_composition_layer_order, "index");
@@ -140,6 +141,16 @@ void *OpenXRExtensionWrapperExtension::set_hand_joint_locations_and_get_next_poi
return nullptr;
}
+void *OpenXRExtensionWrapperExtension::set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) {
+ uint64_t pointer = 0;
+
+ if (GDVIRTUAL_CALL(_set_projection_views_and_get_next_pointer, p_view_index, GDExtensionPtr(p_next_pointer), pointer)) {
+ return reinterpret_cast(pointer);
+ }
+
+ return nullptr;
+}
+
PackedStringArray OpenXRExtensionWrapperExtension::get_suggested_tracker_names() {
PackedStringArray ret;
diff --git a/modules/openxr/extensions/openxr_extension_wrapper_extension.h b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
index 8fc6511277ba..350bcb98307e 100644
--- a/modules/openxr/extensions/openxr_extension_wrapper_extension.h
+++ b/modules/openxr/extensions/openxr_extension_wrapper_extension.h
@@ -60,6 +60,7 @@ class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWra
virtual void *set_session_create_and_get_next_pointer(void *p_next_pointer) override;
virtual void *set_swapchain_create_info_and_get_next_pointer(void *p_next_pointer) override;
virtual void *set_hand_joint_locations_and_get_next_pointer(int p_hand_index, void *p_next_pointer) override;
+ virtual void *set_projection_views_and_get_next_pointer(int p_view_index, void *p_next_pointer) override;
virtual int get_composition_layer_count() override;
virtual XrCompositionLayerBaseHeader *get_composition_layer(int p_index) override;
@@ -71,6 +72,7 @@ class OpenXRExtensionWrapperExtension : public Object, public OpenXRExtensionWra
GDVIRTUAL1R(uint64_t, _set_session_create_and_get_next_pointer, GDExtensionPtr);
GDVIRTUAL1R(uint64_t, _set_swapchain_create_info_and_get_next_pointer, GDExtensionPtr);
GDVIRTUAL2R(uint64_t, _set_hand_joint_locations_and_get_next_pointer, int, GDExtensionPtr);
+ GDVIRTUAL2R(uint64_t, _set_projection_views_and_get_next_pointer, int, GDExtensionPtr);
GDVIRTUAL0R(int, _get_composition_layer_count);
GDVIRTUAL1R(uint64_t, _get_composition_layer, int);
GDVIRTUAL1R(int, _get_composition_layer_order, int);
diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp
index 17755417578a..ae2632564e8b 100644
--- a/modules/openxr/openxr_api.cpp
+++ b/modules/openxr/openxr_api.cpp
@@ -1916,6 +1916,9 @@ bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z
}
}
+ render_state.z_near = p_z_near;
+ render_state.z_far = p_z_far;
+
// now update our projection
return graphics_extension->create_projection_fov(render_state.views[p_view].fov, p_z_near, p_z_far, p_camera_matrix);
}
@@ -2343,6 +2346,30 @@ RID OpenXRAPI::get_depth_texture() {
}
}
+void OpenXRAPI::set_velocity_texture(RID p_render_target) {
+ velocity_texture = p_render_target;
+}
+
+RID OpenXRAPI::get_velocity_texture() {
+ return velocity_texture;
+}
+
+void OpenXRAPI::set_velocity_depth_texture(RID p_render_target) {
+ velocity_depth_texture = p_render_target;
+}
+
+RID OpenXRAPI::get_velocity_depth_texture() {
+ return velocity_depth_texture;
+}
+
+void OpenXRAPI::set_velocity_target_size(const Size2i &p_target_size) {
+ velocity_target_size = p_target_size;
+}
+
+Size2i OpenXRAPI::get_velocity_target_size() {
+ return velocity_target_size;
+}
+
void OpenXRAPI::post_draw_viewport(RID p_render_target) {
// Must be called from rendering thread!
ERR_NOT_ON_RENDER_THREAD;
@@ -2448,6 +2475,20 @@ void OpenXRAPI::end_frame() {
render_state.view_count, // viewCount
render_state.projection_views, // views
};
+
+ if (projection_views_extensions.size() > 0) {
+ for (uint32_t v = 0; v < render_state.view_count; v++) {
+ void *next_pointer = nullptr;
+ for (OpenXRExtensionWrapper *wrapper : projection_views_extensions) {
+ void *np = wrapper->set_projection_views_and_get_next_pointer(v, next_pointer);
+ if (np != nullptr) {
+ next_pointer = np;
+ }
+ }
+ render_state.projection_views[v].next = next_pointer;
+ }
+ }
+
ordered_layers_list.push_back({ (const XrCompositionLayerBaseHeader *)&projection_layer, 0 });
// Sort our layers.
@@ -2578,6 +2619,14 @@ Size2 OpenXRAPI::get_play_space_bounds() const {
return ret;
}
+PackedInt64Array OpenXRAPI::get_supported_swapchain_formats() {
+ PackedInt64Array supported_swapchain_list;
+ for (uint32_t i = 0; i < num_swapchain_formats; i++) {
+ supported_swapchain_list.push_back(supported_swapchain_formats[i]);
+ }
+ return supported_swapchain_list;
+}
+
OpenXRAPI::OpenXRAPI() {
// OpenXRAPI is only constructed if OpenXR is enabled.
singleton = this;
@@ -3499,6 +3548,14 @@ void OpenXRAPI::unregister_composition_layer_provider(OpenXRCompositionLayerProv
composition_layer_providers.erase(provider);
}
+void OpenXRAPI::register_projection_views_extension(OpenXRExtensionWrapper *p_extension) {
+ projection_views_extensions.append(p_extension);
+}
+
+void OpenXRAPI::unregister_projection_views_extension(OpenXRExtensionWrapper *p_extension) {
+ projection_views_extensions.erase(p_extension);
+}
+
const XrEnvironmentBlendMode *OpenXRAPI::get_supported_environment_blend_modes(uint32_t &count) {
count = num_supported_environment_blend_modes;
return supported_environment_blend_modes;
diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h
index ecffce181620..21e18fc5f813 100644
--- a/modules/openxr/openxr_api.h
+++ b/modules/openxr/openxr_api.h
@@ -102,6 +102,9 @@ class OpenXRAPI {
// composition layer providers
Vector composition_layer_providers;
+ // projection views extensions
+ Vector projection_views_extensions;
+
// view configuration
uint32_t num_view_configuration_types = 0;
XrViewConfigurationType *supported_view_configuration_types = nullptr;
@@ -153,7 +156,6 @@ class OpenXRAPI {
enum OpenXRSwapChainTypes {
OPENXR_SWAPCHAIN_COLOR,
OPENXR_SWAPCHAIN_DEPTH,
- // OPENXR_SWAPCHAIN_VELOCITY,
OPENXR_SWAPCHAIN_MAX
};
@@ -165,6 +167,10 @@ class OpenXRAPI {
XrSpace view_space = XR_NULL_HANDLE;
XRPose::TrackingConfidence head_pose_confidence = XRPose::XR_TRACKING_CONFIDENCE_NONE;
+ RID velocity_texture;
+ RID velocity_depth_texture;
+ Size2i velocity_target_size;
+
// When LOCAL_FLOOR isn't supported, we use an approach based on the example code in the
// OpenXR spec in order to emulate it.
// See: https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_EXT_local_floor
@@ -345,6 +351,9 @@ class OpenXRAPI {
bool submit_depth_buffer = false; // if set to true we submit depth buffers to OpenXR if a suitable extension is enabled.
bool view_pose_valid = false;
+ double z_near = 0.0;
+ double z_far = 0.0;
+
Size2i main_swapchain_size;
OpenXRSwapChainInfo main_swapchains[OPENXR_SWAPCHAIN_MAX];
} render_state;
@@ -477,6 +486,12 @@ class OpenXRAPI {
XrSwapchain get_color_swapchain();
RID get_color_texture();
RID get_depth_texture();
+ void set_velocity_texture(RID p_render_target);
+ RID get_velocity_texture();
+ void set_velocity_depth_texture(RID p_render_target);
+ RID get_velocity_depth_texture();
+ void set_velocity_target_size(const Size2i &p_target_size);
+ Size2i get_velocity_target_size();
void post_draw_viewport(RID p_render_target);
void end_frame();
@@ -502,9 +517,13 @@ class OpenXRAPI {
Size2 get_play_space_bounds() const;
// swapchains
+ PackedInt64Array get_supported_swapchain_formats();
int64_t get_color_swapchain_format() const { return color_swapchain_format; }
int64_t get_depth_swapchain_format() const { return depth_swapchain_format; }
+ double get_render_state_z_near() const { return render_state.z_near; }
+ double get_render_state_z_far() const { return render_state.z_far; }
+
// action map
String get_default_action_map_resource_name();
@@ -542,6 +561,9 @@ class OpenXRAPI {
void register_composition_layer_provider(OpenXRCompositionLayerProvider *provider);
void unregister_composition_layer_provider(OpenXRCompositionLayerProvider *provider);
+ void register_projection_views_extension(OpenXRExtensionWrapper *p_extension);
+ void unregister_projection_views_extension(OpenXRExtensionWrapper *p_extension);
+
const XrEnvironmentBlendMode *get_supported_environment_blend_modes(uint32_t &count);
bool is_environment_blend_mode_supported(XrEnvironmentBlendMode p_blend_mode) const;
bool set_environment_blend_mode(XrEnvironmentBlendMode p_blend_mode);
diff --git a/modules/openxr/openxr_api_extension.cpp b/modules/openxr/openxr_api_extension.cpp
index f3bc178d3a25..506e1fc64d35 100644
--- a/modules/openxr/openxr_api_extension.cpp
+++ b/modules/openxr/openxr_api_extension.cpp
@@ -61,6 +61,25 @@ void OpenXRAPIExtension::_bind_methods() {
ClassDB::bind_method(D_METHOD("register_composition_layer_provider", "extension"), &OpenXRAPIExtension::register_composition_layer_provider);
ClassDB::bind_method(D_METHOD("unregister_composition_layer_provider", "extension"), &OpenXRAPIExtension::unregister_composition_layer_provider);
+ ClassDB::bind_method(D_METHOD("register_projection_views_extension", "extension"), &OpenXRAPIExtension::register_projection_views_extension);
+ ClassDB::bind_method(D_METHOD("unregister_projection_views_extension", "extension"), &OpenXRAPIExtension::unregister_projection_views_extension);
+
+ ClassDB::bind_method(D_METHOD("get_render_state_z_near"), &OpenXRAPIExtension::get_render_state_z_near);
+ ClassDB::bind_method(D_METHOD("get_render_state_z_far"), &OpenXRAPIExtension::get_render_state_z_far);
+
+ ClassDB::bind_method(D_METHOD("set_velocity_texture", "render_target"), &OpenXRAPIExtension::set_velocity_texture);
+ ClassDB::bind_method(D_METHOD("set_velocity_depth_texture", "render_target"), &OpenXRAPIExtension::set_velocity_depth_texture);
+ ClassDB::bind_method(D_METHOD("set_velocity_target_size", "target_size"), &OpenXRAPIExtension::set_velocity_target_size);
+
+ ClassDB::bind_method(D_METHOD("get_supported_swapchain_formats"), &OpenXRAPIExtension::get_supported_swapchain_formats);
+
+ ClassDB::bind_method(D_METHOD("openxr_swapchain_create", "create_flags", "usage_flags", "swapchain_format", "width", "height", "sample_count", "array_size"), &OpenXRAPIExtension::openxr_swapchain_create);
+ ClassDB::bind_method(D_METHOD("openxr_swapchain_free", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_free);
+ ClassDB::bind_method(D_METHOD("openxr_swapchain_get_swapchain", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_get_swapchain);
+ ClassDB::bind_method(D_METHOD("openxr_swapchain_acquire", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_acquire);
+ ClassDB::bind_method(D_METHOD("openxr_swapchain_get_image", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_get_image);
+ ClassDB::bind_method(D_METHOD("openxr_swapchain_release", "swapchain"), &OpenXRAPIExtension::openxr_swapchain_release);
+
ClassDB::bind_method(D_METHOD("set_emulate_environment_blend_mode_alpha_blend", "enabled"), &OpenXRAPIExtension::set_emulate_environment_blend_mode_alpha_blend);
ClassDB::bind_method(D_METHOD("is_environment_blend_mode_alpha_supported"), &OpenXRAPIExtension::is_environment_blend_mode_alpha_blend_supported);
@@ -193,6 +212,94 @@ void OpenXRAPIExtension::unregister_composition_layer_provider(OpenXRExtensionWr
OpenXRAPI::get_singleton()->unregister_composition_layer_provider(p_extension);
}
+void OpenXRAPIExtension::register_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+ OpenXRAPI::get_singleton()->register_projection_views_extension(p_extension);
+}
+
+void OpenXRAPIExtension::unregister_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+ OpenXRAPI::get_singleton()->unregister_projection_views_extension(p_extension);
+}
+
+double OpenXRAPIExtension::get_render_state_z_near() {
+ ERR_NOT_ON_RENDER_THREAD_V(0.0);
+ ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0.0);
+ return OpenXRAPI::get_singleton()->get_render_state_z_near();
+}
+
+double OpenXRAPIExtension::get_render_state_z_far() {
+ ERR_NOT_ON_RENDER_THREAD_V(0.0);
+ ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0.0);
+ return OpenXRAPI::get_singleton()->get_render_state_z_far();
+}
+
+void OpenXRAPIExtension::set_velocity_texture(RID p_render_target) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+ OpenXRAPI::get_singleton()->set_velocity_texture(p_render_target);
+}
+
+void OpenXRAPIExtension::set_velocity_depth_texture(RID p_render_target) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+ OpenXRAPI::get_singleton()->set_velocity_depth_texture(p_render_target);
+}
+
+void OpenXRAPIExtension::set_velocity_target_size(const Size2i &p_target_size) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+ OpenXRAPI::get_singleton()->set_velocity_target_size(p_target_size);
+}
+
+PackedInt64Array OpenXRAPIExtension::get_supported_swapchain_formats() {
+ ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), PackedInt64Array());
+ return OpenXRAPI::get_singleton()->get_supported_swapchain_formats();
+}
+
+uint64_t OpenXRAPIExtension::openxr_swapchain_create(XrSwapchainCreateFlags p_create_flags, XrSwapchainUsageFlags p_usage_flags, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size) {
+ ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0);
+
+ OpenXRAPI::OpenXRSwapChainInfo *new_swapchain_info = memnew(OpenXRAPI::OpenXRSwapChainInfo);
+ new_swapchain_info->create(p_create_flags, p_usage_flags, p_swapchain_format, p_width, p_height, p_sample_count, p_array_size);
+ return reinterpret_cast(new_swapchain_info);
+}
+
+void OpenXRAPIExtension::openxr_swapchain_free(uint64_t p_swapchain_info) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+
+ OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info);
+ swapchain_info->free();
+ memfree(swapchain_info);
+}
+
+uint64_t OpenXRAPIExtension::openxr_swapchain_get_swapchain(uint64_t p_swapchain_info) {
+ ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), 0);
+
+ OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info);
+ XrSwapchain swapchain = swapchain_info->get_swapchain();
+ return reinterpret_cast(swapchain);
+}
+
+void OpenXRAPIExtension::openxr_swapchain_acquire(uint64_t p_swapchain_info) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+
+ OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info);
+ bool should_render = true; // Can ignore should_render.
+ swapchain_info->acquire(should_render);
+}
+
+RID OpenXRAPIExtension::openxr_swapchain_get_image(uint64_t p_swapchain_info) {
+ ERR_FAIL_NULL_V(OpenXRAPI::get_singleton(), RID());
+
+ OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info);
+ return swapchain_info->get_image();
+}
+
+void OpenXRAPIExtension::openxr_swapchain_release(uint64_t p_swapchain_info) {
+ ERR_FAIL_NULL(OpenXRAPI::get_singleton());
+
+ OpenXRAPI::OpenXRSwapChainInfo *swapchain_info = reinterpret_cast(p_swapchain_info);
+ swapchain_info->release();
+}
+
void OpenXRAPIExtension::set_emulate_environment_blend_mode_alpha_blend(bool p_enabled) {
ERR_FAIL_NULL(OpenXRAPI::get_singleton());
OpenXRAPI::get_singleton()->set_emulate_environment_blend_mode_alpha_blend(p_enabled);
diff --git a/modules/openxr/openxr_api_extension.h b/modules/openxr/openxr_api_extension.h
index 1b88b418f61f..6519aea7f1a2 100644
--- a/modules/openxr/openxr_api_extension.h
+++ b/modules/openxr/openxr_api_extension.h
@@ -82,6 +82,25 @@ class OpenXRAPIExtension : public RefCounted {
void register_composition_layer_provider(OpenXRExtensionWrapperExtension *p_extension);
void unregister_composition_layer_provider(OpenXRExtensionWrapperExtension *p_extension);
+ void register_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension);
+ void unregister_projection_views_extension(OpenXRExtensionWrapperExtension *p_extension);
+
+ double get_render_state_z_near();
+ double get_render_state_z_far();
+
+ void set_velocity_texture(RID p_render_target);
+ void set_velocity_depth_texture(RID p_render_target);
+ void set_velocity_target_size(const Size2i &p_target_size);
+
+ PackedInt64Array get_supported_swapchain_formats();
+
+ uint64_t openxr_swapchain_create(XrSwapchainCreateFlags p_create_flags, XrSwapchainUsageFlags p_usage_flags, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size);
+ void openxr_swapchain_free(uint64_t p_swapchain_info);
+ uint64_t openxr_swapchain_get_swapchain(uint64_t p_swapchain_info);
+ void openxr_swapchain_acquire(uint64_t p_swapchain_info);
+ RID openxr_swapchain_get_image(uint64_t p_swapchain_info);
+ void openxr_swapchain_release(uint64_t p_swapchain_info);
+
enum OpenXRAlphaBlendModeSupport {
OPENXR_ALPHA_BLEND_MODE_SUPPORT_NONE = 0,
OPENXR_ALPHA_BLEND_MODE_SUPPORT_REAL = 1,
diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp
index 68e04694e3d0..f7f47f36e86a 100644
--- a/modules/openxr/openxr_interface.cpp
+++ b/modules/openxr/openxr_interface.cpp
@@ -1053,6 +1053,30 @@ RID OpenXRInterface::get_depth_texture() {
}
}
+RID OpenXRInterface::get_velocity_texture() {
+ if (openxr_api) {
+ return openxr_api->get_velocity_texture();
+ } else {
+ return RID();
+ }
+}
+
+RID OpenXRInterface::get_velocity_depth_texture() {
+ if (openxr_api) {
+ return openxr_api->get_velocity_depth_texture();
+ } else {
+ return RID();
+ }
+}
+
+Size2i OpenXRInterface::get_velocity_target_size() {
+ if (openxr_api) {
+ return openxr_api->get_velocity_target_size();
+ } else {
+ return Size2i();
+ }
+}
+
void OpenXRInterface::handle_hand_tracking(const String &p_path, OpenXRHandTrackingExtension::HandTrackedHands p_hand) {
OpenXRHandTrackingExtension *hand_tracking_ext = OpenXRHandTrackingExtension::get_singleton();
if (hand_tracking_ext && hand_tracking_ext->get_active()) {
diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h
index d1bf2aaf7878..b37c2eda2901 100644
--- a/modules/openxr/openxr_interface.h
+++ b/modules/openxr/openxr_interface.h
@@ -185,6 +185,9 @@ class OpenXRInterface : public XRInterface {
virtual RID get_color_texture() override;
virtual RID get_depth_texture() override;
+ virtual RID get_velocity_texture() override;
+ virtual RID get_velocity_depth_texture() override;
+ virtual Size2i get_velocity_target_size() override;
virtual void process() override;
virtual void pre_render() override;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1a047dfa2765..68085edbb19c 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -4527,7 +4527,7 @@ void Viewport::set_use_xr(bool p_use_xr) {
// Reset render target override textures.
RID rt = RS::get_singleton()->viewport_get_render_target(viewport);
- RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID());
+ RSG::texture_storage->render_target_set_override(rt, RID(), RID(), RID(), RID());
}
}
}
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 63eb441915ee..35135ce860e0 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -200,12 +200,16 @@ class TextureStorage : public RendererTextureStorage {
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(); }
- virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override {}
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override {}
virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); }
virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); }
virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); }
+ virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); }
virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
+
+ virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
+ virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(0, 0); }
};
} // namespace RendererDummy
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 697d9490158e..52eacb160937 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -3436,7 +3436,7 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) {
return rt->texture;
}
-void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) {
+void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_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 3d281cf98a23..cfd85b28167f 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -779,15 +779,19 @@ class TextureStorage : public RendererTextureStorage {
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;
- virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override;
virtual RID render_target_get_override_color(RID p_render_target) const override;
virtual RID render_target_get_override_depth(RID p_render_target) const override;
RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const;
virtual RID render_target_get_override_velocity(RID p_render_target) const override;
RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const;
+ virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); }
virtual RID render_target_get_texture(RID p_render_target) override;
+ virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
+ virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(0, 0); }
+
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer);
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 4d6435f48a53..cdb055f1f0c0 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -789,7 +789,16 @@ void RendererViewport::draw_viewports(bool p_swap_buffers) {
RSG::texture_storage->render_target_set_override(vp->render_target,
xr_interface->get_color_texture(),
xr_interface->get_depth_texture(),
- xr_interface->get_velocity_texture());
+ xr_interface->get_velocity_texture(),
+ xr_interface->get_velocity_depth_texture());
+
+ RSG::texture_storage->render_target_set_velocity_target_size(vp->render_target, xr_interface->get_velocity_target_size());
+
+ if (xr_interface->get_velocity_texture().is_valid()) {
+ viewport_set_force_motion_vectors(vp->self, true);
+ } else {
+ viewport_set_force_motion_vectors(vp->self, false);
+ }
// render...
RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -990,7 +999,7 @@ void RendererViewport::_viewport_set_size(Viewport *p_viewport, int p_width, int
}
bool RendererViewport::_viewport_requires_motion_vectors(Viewport *p_viewport) {
- return p_viewport->use_taa || p_viewport->scaling_3d_mode == RenderingServer::VIEWPORT_SCALING_3D_MODE_FSR2 || p_viewport->debug_draw == RenderingServer::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS;
+ return p_viewport->use_taa || p_viewport->scaling_3d_mode == RenderingServer::VIEWPORT_SCALING_3D_MODE_FSR2 || p_viewport->debug_draw == RenderingServer::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS || p_viewport->force_motion_vectors;
}
void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
@@ -1338,6 +1347,25 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
_configure_3d_render_buffers(viewport);
}
+void RendererViewport::viewport_set_force_motion_vectors(RID p_viewport, bool p_force_motion_vectors) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_NULL(viewport);
+
+ if (viewport->force_motion_vectors == p_force_motion_vectors) {
+ return;
+ }
+
+ bool motion_vectors_before = _viewport_requires_motion_vectors(viewport);
+ viewport->force_motion_vectors = p_force_motion_vectors;
+
+ bool motion_vectors_after = _viewport_requires_motion_vectors(viewport);
+ if (motion_vectors_before != motion_vectors_after) {
+ num_viewports_with_motion_vectors += motion_vectors_after ? 1 : -1;
+ }
+
+ _configure_3d_render_buffers(viewport);
+}
+
void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) {
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 bf97905f8694..21cc06d6e7ab 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -77,6 +77,7 @@ class RendererViewport {
RS::ViewportScreenSpaceAA screen_space_aa = RenderingServer::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
bool use_taa = false;
bool use_debanding = false;
+ bool force_motion_vectors = false;
RendererSceneRender::CameraData prev_camera_data;
uint64_t prev_camera_data_frame = 0;
@@ -277,6 +278,7 @@ class RendererViewport {
void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode);
void viewport_set_use_taa(RID p_viewport, bool p_use_taa);
void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding);
+ void viewport_set_force_motion_vectors(RID p_viewport, bool p_force_motion_vectors);
void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling);
void viewport_set_occlusion_rays_per_thread(int p_rays_per_thread);
void viewport_set_occlusion_culling_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality);
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 29b1e163c78a..4cad8682e04a 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -724,6 +724,7 @@ class RenderingServerDefault : public RenderingServer {
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
FUNC2(viewport_set_use_taa, RID, bool)
FUNC2(viewport_set_use_debanding, RID, bool)
+ FUNC2(viewport_set_force_motion_vectors, RID, bool)
FUNC2(viewport_set_use_occlusion_culling, RID, bool)
FUNC1(viewport_set_occlusion_rays_per_thread, int)
FUNC1(viewport_set_occlusion_culling_build_quality, ViewportOcclusionCullingBuildQuality)
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index e5283848915c..45e21a70556f 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -178,13 +178,18 @@ class RendererTextureStorage {
virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0;
// override color, depth and velocity buffers (depth and velocity only for 3D)
- virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) = 0;
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) = 0;
virtual RID render_target_get_override_color(RID p_render_target) const = 0;
virtual RID render_target_get_override_depth(RID p_render_target) const = 0;
virtual RID render_target_get_override_velocity(RID p_render_target) const = 0;
+ virtual RID render_target_get_override_velocity_depth(RID p_render_target) const = 0;
// get textures
virtual RID render_target_get_texture(RID p_render_target) = 0;
+
+ // Motion vectors
+ virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) = 0;
+ virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const = 0;
};
#endif // TEXTURE_STORAGE_H
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 0917af73c6a6..9a379e12d1f9 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -1015,6 +1015,8 @@ class RenderingServer : public Object {
virtual void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) = 0;
+ virtual void viewport_set_force_motion_vectors(RID p_viewport, bool p_force_motion_vectors) = 0;
+
virtual void viewport_set_mesh_lod_threshold(RID p_viewport, float p_pixels) = 0;
virtual void viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) = 0;
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index e9d2fc85203b..c7fc017d7816 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -187,6 +187,14 @@ RID XRInterface::get_velocity_texture() {
return RID();
}
+RID XRInterface::get_velocity_depth_texture() {
+ return RID();
+}
+
+Size2i XRInterface::get_velocity_target_size() {
+ return Size2i();
+}
+
PackedStringArray XRInterface::get_suggested_tracker_names() const {
PackedStringArray arr;
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index abd5476fc93b..883eb9cbc5f9 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -137,6 +137,8 @@ class XRInterface : public RefCounted {
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) */
+ virtual RID get_velocity_depth_texture();
+ virtual Size2i get_velocity_target_size();
virtual void pre_render() {}
virtual bool pre_draw_viewport(RID p_render_target) { return true; } /* inform XR interface we are about to start our viewport draw process */
virtual Vector post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* inform XR interface we finished our viewport draw process */