-
-
Notifications
You must be signed in to change notification settings - Fork 21.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OpenXR: Allow composition layers to enable hole punching #91485
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,13 @@ | |
|
||
HashSet<SubViewport *> OpenXRCompositionLayer::viewports_in_use; | ||
|
||
static const char *HOLE_PUNCH_SHADER_CODE = | ||
"shader_type spatial;\n" | ||
"render_mode blend_mix, depth_draw_opaque, cull_back, shadow_to_opacity, shadows_disabled;\n" | ||
"void fragment() {\n" | ||
"\tALBEDO = vec3(0.0, 0.0, 0.0);\n" | ||
"}\n"; | ||
|
||
OpenXRCompositionLayer::OpenXRCompositionLayer() { | ||
openxr_api = OpenXRAPI::get_singleton(); | ||
composition_layer_extension = OpenXRCompositionLayerExtension::get_singleton(); | ||
|
@@ -80,6 +87,9 @@ void OpenXRCompositionLayer::_bind_methods() { | |
ClassDB::bind_method(D_METHOD("set_layer_viewport", "viewport"), &OpenXRCompositionLayer::set_layer_viewport); | ||
ClassDB::bind_method(D_METHOD("get_layer_viewport"), &OpenXRCompositionLayer::get_layer_viewport); | ||
|
||
ClassDB::bind_method(D_METHOD("set_enable_hole_punch", "enable"), &OpenXRCompositionLayer::set_enable_hole_punch); | ||
ClassDB::bind_method(D_METHOD("get_enable_hole_punch"), &OpenXRCompositionLayer::get_enable_hole_punch); | ||
|
||
ClassDB::bind_method(D_METHOD("set_sort_order", "order"), &OpenXRCompositionLayer::set_sort_order); | ||
ClassDB::bind_method(D_METHOD("get_sort_order"), &OpenXRCompositionLayer::get_sort_order); | ||
|
||
|
@@ -93,6 +103,16 @@ void OpenXRCompositionLayer::_bind_methods() { | |
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "layer_viewport", PROPERTY_HINT_NODE_TYPE, "SubViewport"), "set_layer_viewport", "get_layer_viewport"); | ||
ADD_PROPERTY(PropertyInfo(Variant::INT, "sort_order", PROPERTY_HINT_NONE, ""), "set_sort_order", "get_sort_order"); | ||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alpha_blend", PROPERTY_HINT_NONE, ""), "set_alpha_blend", "get_alpha_blend"); | ||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enable_hole_punch", PROPERTY_HINT_NONE, ""), "set_enable_hole_punch", "get_enable_hole_punch"); | ||
} | ||
|
||
bool OpenXRCompositionLayer::_should_use_fallback_node() { | ||
if (Engine::get_singleton()->is_editor_hint()) { | ||
return true; | ||
} else if (openxr_session_running) { | ||
return enable_hole_punch || !is_natively_supported(); | ||
} | ||
return false; | ||
} | ||
|
||
void OpenXRCompositionLayer::_create_fallback_node() { | ||
|
@@ -103,21 +123,27 @@ void OpenXRCompositionLayer::_create_fallback_node() { | |
should_update_fallback_mesh = true; | ||
} | ||
|
||
void OpenXRCompositionLayer::_remove_fallback_node() { | ||
ERR_FAIL_COND(fallback != nullptr); | ||
remove_child(fallback); | ||
fallback->queue_free(); | ||
fallback = nullptr; | ||
} | ||
|
||
void OpenXRCompositionLayer::_on_openxr_session_begun() { | ||
if (!is_natively_supported()) { | ||
if (!fallback) { | ||
_create_fallback_node(); | ||
} | ||
} else if (layer_viewport && is_visible() && is_inside_tree()) { | ||
openxr_session_running = true; | ||
if (layer_viewport && is_natively_supported() && is_visible() && is_inside_tree()) { | ||
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size()); | ||
} | ||
if (!fallback && _should_use_fallback_node()) { | ||
_create_fallback_node(); | ||
} | ||
} | ||
|
||
void OpenXRCompositionLayer::_on_openxr_session_stopping() { | ||
if (fallback && !Engine::get_singleton()->is_editor_hint()) { | ||
fallback->queue_free(); | ||
remove_child(fallback); | ||
fallback = nullptr; | ||
openxr_session_running = false; | ||
if (fallback && !_should_use_fallback_node()) { | ||
_remove_fallback_node(); | ||
} else { | ||
openxr_layer_provider->set_viewport(RID(), Size2i()); | ||
} | ||
|
@@ -152,7 +178,7 @@ void OpenXRCompositionLayer::set_layer_viewport(SubViewport *p_viewport) { | |
|
||
if (fallback) { | ||
_reset_fallback_material(); | ||
} else if (openxr_api && openxr_api->is_running() && is_visible() && is_inside_tree()) { | ||
} else if (openxr_session_running && is_visible() && is_inside_tree()) { | ||
if (layer_viewport) { | ||
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size()); | ||
} else { | ||
|
@@ -165,9 +191,33 @@ SubViewport *OpenXRCompositionLayer::get_layer_viewport() const { | |
return layer_viewport; | ||
} | ||
|
||
void OpenXRCompositionLayer::set_enable_hole_punch(bool p_enable) { | ||
if (enable_hole_punch == p_enable) { | ||
return; | ||
} | ||
|
||
enable_hole_punch = p_enable; | ||
if (_should_use_fallback_node()) { | ||
if (fallback) { | ||
_reset_fallback_material(); | ||
} else { | ||
_create_fallback_node(); | ||
} | ||
} else if (fallback) { | ||
_remove_fallback_node(); | ||
} | ||
|
||
update_configuration_warnings(); | ||
} | ||
|
||
bool OpenXRCompositionLayer::get_enable_hole_punch() const { | ||
return enable_hole_punch; | ||
} | ||
|
||
void OpenXRCompositionLayer::set_sort_order(int p_order) { | ||
if (openxr_layer_provider) { | ||
openxr_layer_provider->set_sort_order(p_order); | ||
update_configuration_warnings(); | ||
} | ||
} | ||
|
||
|
@@ -212,15 +262,28 @@ void OpenXRCompositionLayer::_reset_fallback_material() { | |
return; | ||
} | ||
|
||
if (layer_viewport) { | ||
if (enable_hole_punch && !Engine::get_singleton()->is_editor_hint() && is_natively_supported()) { | ||
Ref<ShaderMaterial> material = fallback->get_surface_override_material(0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be reading this wrong but what happens if I need the fallback and I have hole punch enabled? Wouldn't this override the material that renders my viewport? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, if you were on a platform that didn't natively support composition layers and you needed the "real" fallback mesh, then this code block wouldn't run because |
||
if (material.is_null()) { | ||
Ref<Shader> shader; | ||
shader.instantiate(); | ||
shader->set_code(HOLE_PUNCH_SHADER_CODE); | ||
|
||
material.instantiate(); | ||
material->set_shader(shader); | ||
|
||
fallback->set_surface_override_material(0, material); | ||
} | ||
} else if (layer_viewport) { | ||
dsnopek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Ref<StandardMaterial3D> material = fallback->get_surface_override_material(0); | ||
if (material.is_null()) { | ||
material.instantiate(); | ||
material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); | ||
material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true); | ||
material->set_local_to_scene(true); | ||
fallback->set_surface_override_material(0, material); | ||
} | ||
|
||
material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, !enable_hole_punch); | ||
material->set_transparency(get_alpha_blend() ? StandardMaterial3D::TRANSPARENCY_ALPHA : StandardMaterial3D::TRANSPARENCY_DISABLED); | ||
|
||
Ref<ViewportTexture> texture = material->get_texture(StandardMaterial3D::TEXTURE_ALBEDO); | ||
|
@@ -260,7 +323,7 @@ void OpenXRCompositionLayer::_notification(int p_what) { | |
} | ||
} break; | ||
case NOTIFICATION_VISIBILITY_CHANGED: { | ||
if (!fallback && openxr_api && openxr_api->is_running() && is_inside_tree()) { | ||
if (!fallback && openxr_session_running && is_inside_tree()) { | ||
if (layer_viewport && is_visible()) { | ||
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size()); | ||
} else { | ||
|
@@ -277,7 +340,7 @@ void OpenXRCompositionLayer::_notification(int p_what) { | |
composition_layer_extension->register_viewport_composition_layer_provider(openxr_layer_provider); | ||
} | ||
|
||
if (!fallback && layer_viewport && openxr_api && openxr_api->is_running() && is_visible()) { | ||
if (!fallback && layer_viewport && openxr_session_running && is_visible()) { | ||
openxr_layer_provider->set_viewport(layer_viewport->get_viewport_rid(), layer_viewport->get_size()); | ||
} | ||
} break; | ||
|
@@ -347,5 +410,9 @@ PackedStringArray OpenXRCompositionLayer::get_configuration_warnings() const { | |
warnings.push_back(RTR("OpenXR composition layers must have orthonormalized transforms (ie. no scale or shearing).")); | ||
} | ||
|
||
if (enable_hole_punch && get_sort_order() >= 0) { | ||
warnings.push_back(RTR("Hole punching won't work as expected unless the sort order is less than zero.")); | ||
} | ||
|
||
return warnings; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly safer to just do
if (fallback)
. If there shouldn't be a fallback node, it won't have been created.This could potentially create a leak where the fallback was created, but since then the dev disabled hole punch, so we don't remove the fallback because now the
_should_use_fallback_node
returns false.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. There's really no risk of a leak here, because
fallback
is a node that's a child of the composition layer node, so it'll automatically get cleaned whenever the composition layer node is cleaned up. And, if the dev changed the hole punch setting, it would already have gotten cleaned up inset_enable_hole_punch()
. But even beyond that, if_should_use_fallback_node()
now returnedfalse
, we would still clean it up, because we're checking for!_should_use_fallback_node()
(negated with!
) in the above code.So, I personally think this code is fine as it is.