Преглед изворни кода

Merge pull request #81561 from BastiaanOlij/fix_openxr_blend_modes

Fix issue with OpenXR environment blend mode not being applied properly
Yuri Sizov пре 2 година
родитељ
комит
495b89ece9

+ 3 - 0
doc/classes/ProjectSettings.xml

@@ -2706,6 +2706,9 @@
 		<member name="xr/openxr/enabled" type="bool" setter="" getter="" default="false">
 			If [code]true[/code] Godot will setup and initialize OpenXR on startup.
 		</member>
+		<member name="xr/openxr/environment_blend_mode" type="int" setter="" getter="" default="&quot;0&quot;">
+			Specify how OpenXR should blend in the environment. This is specific to certain AR and passthrough devices where camera images are blended in by the XR compositor.
+		</member>
 		<member name="xr/openxr/form_factor" type="int" setter="" getter="" default="&quot;0&quot;">
 			Specify whether OpenXR should be configured for an HMD or a hand held device.
 		</member>

+ 3 - 0
doc/classes/XRInterface.xml

@@ -188,6 +188,9 @@
 		<member name="ar_is_anchor_detection_enabled" type="bool" setter="set_anchor_detection_is_enabled" getter="get_anchor_detection_is_enabled" default="false">
 			On an AR interface, [code]true[/code] if anchor detection is enabled.
 		</member>
+		<member name="environment_blend_mode" type="int" setter="set_environment_blend_mode" getter="get_environment_blend_mode" enum="XRInterface.EnvironmentBlendMode" default="0">
+			Specify how XR should blend in the environment. This is specific to certain AR and passthrough devices where camera images are blended in by the XR compositor.
+		</member>
 		<member name="interface_is_primary" type="bool" setter="set_primary" getter="is_primary" default="false">
 			[code]true[/code] if this is the primary interface.
 		</member>

+ 1 - 0
main/main.cpp

@@ -2048,6 +2048,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 	GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/form_factor", PROPERTY_HINT_ENUM, "Head Mounted,Handheld"), "0");
 	GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/view_configuration", PROPERTY_HINT_ENUM, "Mono,Stereo"), "1"); // "Mono,Stereo,Quad,Observer"
 	GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/reference_space", PROPERTY_HINT_ENUM, "Local,Stage"), "1");
+	GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "xr/openxr/environment_blend_mode", PROPERTY_HINT_ENUM, "Opaque,Additive,Alpha"), "0");
 
 	GLOBAL_DEF_BASIC("xr/openxr/submit_depth_buffer", false);
 	GLOBAL_DEF_BASIC("xr/openxr/startup_alert", true);

+ 66 - 10
modules/openxr/openxr_api.cpp

@@ -481,11 +481,19 @@ bool OpenXRAPI::load_supported_view_configuration_types() {
 
 	result = xrEnumerateViewConfigurations(instance, system_id, num_view_configuration_types, &num_view_configuration_types, supported_view_configuration_types);
 	ERR_FAIL_COND_V_MSG(XR_FAILED(result), false, "OpenXR: Failed to enumerateview configurations");
+	ERR_FAIL_COND_V_MSG(num_view_configuration_types == 0, false, "OpenXR: Failed to enumerateview configurations"); // JIC there should be at least 1!
 
 	for (uint32_t i = 0; i < num_view_configuration_types; i++) {
 		print_verbose(String("OpenXR: Found supported view configuration ") + OpenXRUtil::get_view_configuration_name(supported_view_configuration_types[i]));
 	}
 
+	// Check value we loaded at startup...
+	if (!is_view_configuration_supported(view_configuration)) {
+		print_verbose(String("OpenXR: ") + OpenXRUtil::get_view_configuration_name(view_configuration) + String(" isn't supported, defaulting to ") + OpenXRUtil::get_view_configuration_name(supported_view_configuration_types[0]));
+
+		view_configuration = supported_view_configuration_types[0];
+	}
+
 	return true;
 }
 
@@ -512,11 +520,19 @@ bool OpenXRAPI::load_supported_environmental_blend_modes() {
 
 	result = xrEnumerateEnvironmentBlendModes(instance, system_id, view_configuration, num_supported_environment_blend_modes, &num_supported_environment_blend_modes, supported_environment_blend_modes);
 	ERR_FAIL_COND_V_MSG(XR_FAILED(result), false, "OpenXR: Failed to enumerate environmental blend modes");
+	ERR_FAIL_COND_V_MSG(num_supported_environment_blend_modes == 0, false, "OpenXR: Failed to enumerate environmental blend modes"); // JIC there should be at least 1!
 
 	for (uint32_t i = 0; i < num_supported_environment_blend_modes; i++) {
 		print_verbose(String("OpenXR: Found environmental blend mode ") + OpenXRUtil::get_environment_blend_mode_name(supported_environment_blend_modes[i]));
 	}
 
+	// Check value we loaded at startup...
+	if (!is_environment_blend_mode_supported(environment_blend_mode)) {
+		print_verbose(String("OpenXR: ") + OpenXRUtil::get_environment_blend_mode_name(environment_blend_mode) + String(" isn't supported, defaulting to ") + OpenXRUtil::get_environment_blend_mode_name(supported_environment_blend_modes[0]));
+
+		environment_blend_mode = supported_environment_blend_modes[0];
+	}
+
 	return true;
 }
 
@@ -665,11 +681,19 @@ bool OpenXRAPI::load_supported_reference_spaces() {
 
 	result = xrEnumerateReferenceSpaces(session, num_reference_spaces, &num_reference_spaces, supported_reference_spaces);
 	ERR_FAIL_COND_V_MSG(XR_FAILED(result), false, "OpenXR: Failed to enumerate reference spaces");
+	ERR_FAIL_COND_V_MSG(num_reference_spaces == 0, false, "OpenXR: Failed to enumerate reference spaces");
 
 	for (uint32_t i = 0; i < num_reference_spaces; i++) {
 		print_verbose(String("OpenXR: Found supported reference space ") + OpenXRUtil::get_reference_space_name(supported_reference_spaces[i]));
 	}
 
+	// Check value we loaded at startup...
+	if (!is_reference_space_supported(reference_space)) {
+		print_verbose(String("OpenXR: ") + OpenXRUtil::get_reference_space_name(reference_space) + String(" isn't supported, defaulting to ") + OpenXRUtil::get_reference_space_name(supported_reference_spaces[0]));
+
+		reference_space = supported_reference_spaces[0];
+	}
+
 	return true;
 }
 
@@ -1924,10 +1948,15 @@ void OpenXRAPI::end_frame() {
 		}
 	}
 
+	XrCompositionLayerFlags layer_flags = XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
+	if (layers_list.size() > 0 || environment_blend_mode != XR_ENVIRONMENT_BLEND_MODE_OPAQUE) {
+		layer_flags |= XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
+	}
+
 	XrCompositionLayerProjection projection_layer = {
 		XR_TYPE_COMPOSITION_LAYER_PROJECTION, // type
 		nullptr, // next
-		layers_list.size() > 0 ? XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT | XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT : XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, // layerFlags
+		layer_flags, // layerFlags
 		play_space, // space
 		view_count, // viewCount
 		projection_views, // views
@@ -1991,8 +2020,8 @@ OpenXRAPI::OpenXRAPI() {
 
 	} else {
 		// Load settings from project settings
-		int ff = GLOBAL_GET("xr/openxr/form_factor");
-		switch (ff) {
+		int form_factor_setting = GLOBAL_GET("xr/openxr/form_factor");
+		switch (form_factor_setting) {
 			case 0: {
 				form_factor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
 			} break;
@@ -2003,8 +2032,8 @@ OpenXRAPI::OpenXRAPI() {
 				break;
 		}
 
-		int vc = GLOBAL_GET("xr/openxr/view_configuration");
-		switch (vc) {
+		int view_configuration_setting = GLOBAL_GET("xr/openxr/view_configuration");
+		switch (view_configuration_setting) {
 			case 0: {
 				view_configuration = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
 			} break;
@@ -2023,8 +2052,8 @@ OpenXRAPI::OpenXRAPI() {
 				break;
 		}
 
-		int rs = GLOBAL_GET("xr/openxr/reference_space");
-		switch (rs) {
+		int reference_space_setting = GLOBAL_GET("xr/openxr/reference_space");
+		switch (reference_space_setting) {
 			case 0: {
 				reference_space = XR_REFERENCE_SPACE_TYPE_LOCAL;
 			} break;
@@ -2035,6 +2064,21 @@ OpenXRAPI::OpenXRAPI() {
 				break;
 		}
 
+		int environment_blend_mode_setting = GLOBAL_GET("xr/openxr/environment_blend_mode");
+		switch (environment_blend_mode_setting) {
+			case 0: {
+				environment_blend_mode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
+			} break;
+			case 1: {
+				environment_blend_mode = XR_ENVIRONMENT_BLEND_MODE_ADDITIVE;
+			} break;
+			case 2: {
+				environment_blend_mode = XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND;
+			} break;
+			default:
+				break;
+		}
+
 		submit_depth_buffer = GLOBAL_GET("xr/openxr/submit_depth_buffer");
 	}
 
@@ -2864,12 +2908,24 @@ const XrEnvironmentBlendMode *OpenXRAPI::get_supported_environment_blend_modes(u
 	return supported_environment_blend_modes;
 }
 
-bool OpenXRAPI::set_environment_blend_mode(XrEnvironmentBlendMode mode) {
+bool OpenXRAPI::is_environment_blend_mode_supported(XrEnvironmentBlendMode p_blend_mode) const {
+	ERR_FAIL_NULL_V(supported_environment_blend_modes, false);
+
 	for (uint32_t i = 0; i < num_supported_environment_blend_modes; i++) {
-		if (supported_environment_blend_modes[i] == mode) {
-			environment_blend_mode = mode;
+		if (supported_environment_blend_modes[i] == p_blend_mode) {
 			return true;
 		}
 	}
+
+	return false;
+}
+
+bool OpenXRAPI::set_environment_blend_mode(XrEnvironmentBlendMode p_blend_mode) {
+	// We allow setting this when not initialised and will check if it is supported when initialising.
+	// After OpenXR is initialised we verify we're setting a supported blend mode.
+	if (!is_initialized() || is_environment_blend_mode_supported(p_blend_mode)) {
+		environment_blend_mode = p_blend_mode;
+		return true;
+	}
 	return false;
 }

+ 3 - 1
modules/openxr/openxr_api.h

@@ -405,7 +405,9 @@ public:
 	void unregister_composition_layer_provider(OpenXRCompositionLayerProvider *provider);
 
 	const XrEnvironmentBlendMode *get_supported_environment_blend_modes(uint32_t &count);
-	bool set_environment_blend_mode(XrEnvironmentBlendMode mode);
+	bool is_environment_blend_mode_supported(XrEnvironmentBlendMode p_blend_mode) const;
+	bool set_environment_blend_mode(XrEnvironmentBlendMode p_blend_mode);
+	XrEnvironmentBlendMode get_environment_blend_mode() const { return environment_blend_mode; }
 
 	OpenXRAPI();
 	~OpenXRAPI();

+ 21 - 0
modules/openxr/openxr_interface.cpp

@@ -985,6 +985,27 @@ Array OpenXRInterface::get_supported_environment_blend_modes() {
 	return modes;
 }
 
+XRInterface::EnvironmentBlendMode OpenXRInterface::get_environment_blend_mode() const {
+	if (openxr_api) {
+		XrEnvironmentBlendMode oxr_blend_mode = openxr_api->get_environment_blend_mode();
+		switch (oxr_blend_mode) {
+			case XR_ENVIRONMENT_BLEND_MODE_OPAQUE: {
+				return XR_ENV_BLEND_MODE_OPAQUE;
+			} break;
+			case XR_ENVIRONMENT_BLEND_MODE_ADDITIVE: {
+				return XR_ENV_BLEND_MODE_ADDITIVE;
+			} break;
+			case XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND: {
+				return XR_ENV_BLEND_MODE_ALPHA_BLEND;
+			} break;
+			default:
+				break;
+		}
+	}
+
+	return XR_ENV_BLEND_MODE_OPAQUE;
+}
+
 bool OpenXRInterface::set_environment_blend_mode(XRInterface::EnvironmentBlendMode mode) {
 	if (openxr_api) {
 		XrEnvironmentBlendMode oxr_blend_mode;

+ 1 - 0
modules/openxr/openxr_interface.h

@@ -152,6 +152,7 @@ public:
 
 	/** environment blend mode. */
 	virtual Array get_supported_environment_blend_modes() override;
+	virtual XRInterface::EnvironmentBlendMode get_environment_blend_mode() const override;
 	virtual bool set_environment_blend_mode(XRInterface::EnvironmentBlendMode mode) override;
 
 	void on_state_ready();

+ 2 - 0
servers/xr/xr_interface.cpp

@@ -79,6 +79,8 @@ void XRInterface::_bind_methods() {
 	/** environment blend mode. */
 	ClassDB::bind_method(D_METHOD("get_supported_environment_blend_modes"), &XRInterface::get_supported_environment_blend_modes);
 	ClassDB::bind_method(D_METHOD("set_environment_blend_mode", "mode"), &XRInterface::set_environment_blend_mode);
+	ClassDB::bind_method(D_METHOD("get_environment_blend_mode"), &XRInterface::get_environment_blend_mode);
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_blend_mode"), "set_environment_blend_mode", "get_environment_blend_mode");
 
 	ADD_GROUP("AR", "ar_");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ar_is_anchor_detection_enabled"), "set_anchor_detection_is_enabled", "get_anchor_detection_is_enabled");

+ 1 - 0
servers/xr/xr_interface.h

@@ -147,6 +147,7 @@ public:
 
 	/** 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; }
 
 	XRInterface();