using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Runtime.InteropServices; using Unity.Collections; using Unity.XR.CoreUtils.Collections; using UnityEngine.Scripting; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.ARKit { /// /// This subsystem provides implementing functionality for the XROcclusionSubsystem class. /// [Preserve] public sealed class ARKitOcclusionSubsystem : XROcclusionSubsystem { [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] static void Register() { if (!Api.AtLeast13_0()) return; const string k_SubsystemId = "ARKit-Occlusion"; var occlusionSubsystemCinfo = new XROcclusionSubsystemDescriptor.Cinfo() { id = k_SubsystemId, providerType = typeof(ARKitOcclusionSubsystem.ARKitProvider), subsystemTypeOverride = typeof(ARKitOcclusionSubsystem), humanSegmentationStencilImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportBodySegmentationStencil, humanSegmentationDepthImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportBodySegmentationDepth, environmentDepthImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth, environmentDepthConfidenceImageSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth, environmentDepthTemporalSmoothingSupportedDelegate = NativeApi.UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepthTemporalSmoothing }; XROcclusionSubsystemDescriptor.Register(occlusionSubsystemCinfo); } class ARKitProvider : Provider { const string k_TextureHumanStencilPropertyName = "_HumanStencil"; const string k_TextureHumanDepthPropertyName = "_HumanDepth"; const string k_TextureEnvironmentDepthPropertyName = "_EnvironmentDepth"; const string k_TextureEnvironmentDepthConfidencePropertyName = "_EnvironmentDepthConfidence"; const string k_HumanEnabledMaterialKeyword = "ARKIT_HUMAN_SEGMENTATION_ENABLED"; const string k_EnvironmentDepthEnabledMaterialKeyword = "ARKIT_ENVIRONMENT_DEPTH_ENABLED"; static readonly int k_TextureHumanStencilPropertyId = Shader.PropertyToID(k_TextureHumanStencilPropertyName); static readonly int k_TextureHumanDepthPropertyId = Shader.PropertyToID(k_TextureHumanDepthPropertyName); static readonly int k_TextureEnvironmentDepthPropertyId = Shader.PropertyToID(k_TextureEnvironmentDepthPropertyName); static readonly int k_TextureEnvironmentDepthConfidencePropertyId = Shader.PropertyToID(k_TextureEnvironmentDepthConfidencePropertyName); /// /// The shader keywords for enabling human segmentation rendering. /// static readonly List k_HumanSegmentationKeywordList = new(){ k_HumanEnabledMaterialKeyword }; static readonly ReadOnlyList k_HumanSegmentationKeywordListReadOnly = new(k_HumanSegmentationKeywordList); /// /// The shader keywords for enabling environment depth rendering. /// static readonly List k_EnvironmentDepthKeywordList = new(){ k_EnvironmentDepthEnabledMaterialKeyword }; static readonly ReadOnlyList k_EnvironmentDepthKeywordListReadOnly = new(k_EnvironmentDepthKeywordList); /// /// Keywords to use when no occlusion is enabled. /// static readonly List k_AllDisabledShaderKeywords = new(){ k_HumanEnabledMaterialKeyword, k_EnvironmentDepthEnabledMaterialKeyword }; static readonly ReadOnlyList k_AllDisabledShaderKeywordsReadOnly = new(k_AllDisabledShaderKeywords); static readonly XRShaderKeywords k_DepthDisabledShaderKeywords = new(null, k_AllDisabledShaderKeywordsReadOnly) ; static readonly XRShaderKeywords k_EnvironmentDepthKeywords = new(k_EnvironmentDepthKeywordListReadOnly, k_HumanSegmentationKeywordListReadOnly); static readonly XRShaderKeywords k_HumanSegmentationKeywords = new(k_HumanSegmentationKeywordListReadOnly, k_EnvironmentDepthKeywordListReadOnly); OcclusionPreferenceMode m_OcclusionPreferenceMode; public ARKitProvider() => NativeApi.UnityARKit_OcclusionProvider_Construct( k_TextureHumanStencilPropertyId, k_TextureHumanDepthPropertyId, k_TextureEnvironmentDepthPropertyId, k_TextureEnvironmentDepthConfidencePropertyId); public override void Start() => NativeApi.UnityARKit_OcclusionProvider_Start(); public override void Stop() => NativeApi.UnityARKit_OcclusionProvider_Stop(); public override void Destroy() => NativeApi.UnityARKit_OcclusionProvider_Destruct(); public override HumanSegmentationStencilMode requestedHumanStencilMode { get => NativeApi.UnityARKit_OcclusionProvider_GetRequestedSegmentationStencilMode(); set { NativeApi.UnityARKit_OcclusionProvider_SetRequestedSegmentationStencilMode(value); Api.SetFeatureRequested(Feature.PeopleOcclusionStencil, value.Enabled()); } } public override HumanSegmentationStencilMode currentHumanStencilMode => NativeApi.UnityARKit_OcclusionProvider_GetCurrentSegmentationStencilMode(); public override HumanSegmentationDepthMode requestedHumanDepthMode { get => NativeApi.UnityARKit_OcclusionProvider_GetRequestedSegmentationDepthMode(); set { NativeApi.UnityARKit_OcclusionProvider_SetRequestedSegmentationDepthMode(value); Api.SetFeatureRequested(Feature.PeopleOcclusionDepth, value.Enabled()); } } public override HumanSegmentationDepthMode currentHumanDepthMode => NativeApi.UnityARKit_OcclusionProvider_GetCurrentSegmentationDepthMode(); public override EnvironmentDepthMode requestedEnvironmentDepthMode { get => NativeApi.UnityARKit_OcclusionProvider_GetRequestedEnvironmentDepthMode(); set { NativeApi.UnityARKit_OcclusionProvider_SetRequestedEnvironmentDepthMode(value); Api.SetFeatureRequested(Feature.EnvironmentDepth, value.Enabled()); } } public override EnvironmentDepthMode currentEnvironmentDepthMode => NativeApi.UnityARKit_OcclusionProvider_GetCurrentEnvironmentDepthMode(); public override bool environmentDepthTemporalSmoothingEnabled => NativeApi.UnityARKit_OcclusionProvider_GetEnvironmentDepthTemporalSmoothingEnabled(); public override bool environmentDepthTemporalSmoothingRequested { get => Api.GetRequestedFeatures().Any(Feature.EnvironmentDepthTemporalSmoothing); set => Api.SetFeatureRequested(Feature.EnvironmentDepthTemporalSmoothing, value); } public override OcclusionPreferenceMode requestedOcclusionPreferenceMode { get => m_OcclusionPreferenceMode; set => m_OcclusionPreferenceMode = value; } public override OcclusionPreferenceMode currentOcclusionPreferenceMode => m_OcclusionPreferenceMode; public override bool TryGetHumanStencil(out XRTextureDescriptor humanStencilDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetHumanStencil(out humanStencilDescriptor); public override XRCpuImage.Api humanStencilCpuImageApi => ARKitCpuImageApi.instance; public override bool TryAcquireHumanStencilCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.HumanStencil, out cinfo); public override bool TryGetHumanDepth(out XRTextureDescriptor humanDepthDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetHumanDepth(out humanDepthDescriptor); public override XRCpuImage.Api humanDepthCpuImageApi => ARKitCpuImageApi.instance; public override bool TryAcquireHumanDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.HumanDepth, out cinfo); public override bool TryGetEnvironmentDepth(out XRTextureDescriptor environmentDepthDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetEnvironmentDepth(out environmentDepthDescriptor); public override bool TryAcquireEnvironmentDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.EnvironmentDepth, out cinfo); public override bool TryAcquireRawEnvironmentDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.RawEnvironmentDepth, out cinfo); public override bool TryAcquireSmoothedEnvironmentDepthCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.TemporallySmoothedEnvironmentDepth, out cinfo); public override XRCpuImage.Api environmentDepthCpuImageApi => ARKitCpuImageApi.instance; public override bool TryGetEnvironmentDepthConfidence(out XRTextureDescriptor environmentDepthConfidenceDescriptor) => NativeApi.UnityARKit_OcclusionProvider_TryGetEnvironmentDepthConfidence(out environmentDepthConfidenceDescriptor); public override bool TryAcquireEnvironmentDepthConfidenceCpuImage(out XRCpuImage.Cinfo cinfo) => ARKitCpuImageApi.TryAcquireLatestImage(ARKitCpuImageApi.ImageType.EnvironmentDepthConfidence, out cinfo); public override XRCpuImage.Api environmentDepthConfidenceCpuImageApi => ARKitCpuImageApi.instance; public override unsafe NativeArray GetTextureDescriptors( XRTextureDescriptor defaultDescriptor, Allocator allocator) { var textureDescriptors = NativeApi.UnityARKit_OcclusionProvider_AcquireTextureDescriptors( out var length, out var elementSize); try { return NativeCopyUtility.PtrToNativeArrayWithDefault( defaultDescriptor, textureDescriptors, elementSize, length, allocator); } finally { NativeApi.UnityARKit_OcclusionProvider_ReleaseTextureDescriptors(textureDescriptors); } } [Obsolete] public override void GetMaterialKeywords(out List enabledKeywords, out List disabledKeywords) { var isEnvDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsEnvironmentEnabled(); var isHumanDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsHumanEnabled(); // If no occlusion is preferred or if neither depth is enabled, then all disable occlusion. if (m_OcclusionPreferenceMode == OcclusionPreferenceMode.NoOcclusion || (!isEnvDepthEnabled && !isHumanDepthEnabled)) { enabledKeywords = null; disabledKeywords = k_AllDisabledShaderKeywords; } // Else if environment depth is enabled and human depth is not enabled/prefered, then use environment depth. else if (isEnvDepthEnabled && (!isHumanDepthEnabled || m_OcclusionPreferenceMode == OcclusionPreferenceMode.PreferEnvironmentOcclusion)) { enabledKeywords = k_EnvironmentDepthKeywordList; disabledKeywords = k_HumanSegmentationKeywordList; } // Otherwise, human depth is enabled and/or preferred, so use human depth. else { enabledKeywords = k_HumanSegmentationKeywordList; disabledKeywords = k_EnvironmentDepthKeywordList; } } [Obsolete] public override ShaderKeywords GetShaderKeywords() { var isEnvDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsEnvironmentEnabled(); var isHumanDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsHumanEnabled(); if (ShouldUseDepthDisabledKeywords(isEnvDepthEnabled, isHumanDepthEnabled)) return new ShaderKeywords(null, k_AllDisabledShaderKeywords.AsReadOnly()); if (ShouldUseEnvironmentDepthEnabledKeywords(isEnvDepthEnabled, isHumanDepthEnabled)) return new ShaderKeywords(k_EnvironmentDepthKeywordList.AsReadOnly(), k_HumanSegmentationKeywordList.AsReadOnly()); return new ShaderKeywords(k_HumanSegmentationKeywordList.AsReadOnly(), k_EnvironmentDepthKeywordList.AsReadOnly()); } public override XRShaderKeywords GetShaderKeywords2() { var isEnvDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsEnvironmentEnabled(); var isHumanDepthEnabled = NativeApi.UnityARKit_OcclusionProvider_IsHumanEnabled(); if (ShouldUseDepthDisabledKeywords(isEnvDepthEnabled, isHumanDepthEnabled)) return k_DepthDisabledShaderKeywords; if (ShouldUseEnvironmentDepthEnabledKeywords(isEnvDepthEnabled, isHumanDepthEnabled)) return k_EnvironmentDepthKeywords; return k_HumanSegmentationKeywords; } bool ShouldUseDepthDisabledKeywords(bool isEnvDepthEnabled, bool isHumanDepthEnabled) { return m_OcclusionPreferenceMode == OcclusionPreferenceMode.NoOcclusion || (!isEnvDepthEnabled && !isHumanDepthEnabled); } bool ShouldUseEnvironmentDepthEnabledKeywords(bool isEnvDepthEnabled, bool isHumanDepthEnabled) { return isEnvDepthEnabled && (!isHumanDepthEnabled || m_OcclusionPreferenceMode == OcclusionPreferenceMode.PreferEnvironmentOcclusion); } } static class NativeApi { #if UNITY_XR_ARKIT_LOADER_ENABLED [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Construct( int textureHumanStencilPropertyId, int textureHumanDepthPropertyId, int textureEnvDepthPropertyId, int textureEnvDepthConfidencePropertyId); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Start(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Stop(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_Destruct(); [DllImport("__Internal")] public static extern HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetRequestedSegmentationStencilMode(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_SetRequestedSegmentationStencilMode(HumanSegmentationStencilMode humanSegmentationStencilMode); [DllImport("__Internal")] public static extern HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetCurrentSegmentationStencilMode(); [DllImport("__Internal")] public static extern HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetRequestedSegmentationDepthMode(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_SetRequestedSegmentationDepthMode(HumanSegmentationDepthMode humanSegmentationDepthMode); [DllImport("__Internal")] public static extern HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetCurrentSegmentationDepthMode(); [DllImport("__Internal")] public static extern EnvironmentDepthMode UnityARKit_OcclusionProvider_GetRequestedEnvironmentDepthMode(); [DllImport("__Internal")] public static extern void UnityARKit_OcclusionProvider_SetRequestedEnvironmentDepthMode(EnvironmentDepthMode environmentDepthMode); [DllImport("__Internal")] public static extern EnvironmentDepthMode UnityARKit_OcclusionProvider_GetCurrentEnvironmentDepthMode(); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_GetEnvironmentDepthTemporalSmoothingEnabled(); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetHumanStencil(out XRTextureDescriptor humanStencilDescriptor); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetHumanDepth(out XRTextureDescriptor humanDepthDescriptor); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepth(out XRTextureDescriptor envDepthDescriptor); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepthConfidence(out XRTextureDescriptor envDepthConfidenceDescriptor); [DllImport("__Internal")] public static extern unsafe void* UnityARKit_OcclusionProvider_AcquireTextureDescriptors(out int length, out int elementSize); [DllImport("__Internal")] public static extern unsafe void UnityARKit_OcclusionProvider_ReleaseTextureDescriptors(void* descriptors); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_IsHumanEnabled(); [DllImport("__Internal")] public static extern bool UnityARKit_OcclusionProvider_IsEnvironmentEnabled(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationStencil(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationDepth(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth(); [DllImport("__Internal")] public static extern Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepthTemporalSmoothing(); #else static readonly string k_ExceptionMsg = "Apple ARKit XR Plug-in Provider not enabled in project settings."; public static void UnityARKit_OcclusionProvider_Construct( int textureHumanStencilPropertyId, int textureHumanDepthPropertyId, int textureEnvDepthPropertyId, int textureEnvDepthConfidencePropertyId) => throw new NotImplementedException(k_ExceptionMsg); public static void UnityARKit_OcclusionProvider_Start() => throw new NotImplementedException(k_ExceptionMsg); public static void UnityARKit_OcclusionProvider_Stop() => throw new NotImplementedException(k_ExceptionMsg); public static void UnityARKit_OcclusionProvider_Destruct() => throw new NotImplementedException(k_ExceptionMsg); public static HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetRequestedSegmentationStencilMode() => throw new NotImplementedException(k_ExceptionMsg); public static void UnityARKit_OcclusionProvider_SetRequestedSegmentationStencilMode( HumanSegmentationStencilMode humanSegmentationStencilMode) => throw new NotImplementedException(k_ExceptionMsg); public static HumanSegmentationStencilMode UnityARKit_OcclusionProvider_GetCurrentSegmentationStencilMode() => throw new NotImplementedException(k_ExceptionMsg); public static HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetRequestedSegmentationDepthMode() => throw new NotImplementedException(k_ExceptionMsg); public static void UnityARKit_OcclusionProvider_SetRequestedSegmentationDepthMode( HumanSegmentationDepthMode humanSegmentationDepthMode) => throw new NotImplementedException(k_ExceptionMsg); public static HumanSegmentationDepthMode UnityARKit_OcclusionProvider_GetCurrentSegmentationDepthMode() => throw new NotImplementedException(k_ExceptionMsg); public static EnvironmentDepthMode UnityARKit_OcclusionProvider_GetRequestedEnvironmentDepthMode() => throw new NotImplementedException(k_ExceptionMsg); public static void UnityARKit_OcclusionProvider_SetRequestedEnvironmentDepthMode( EnvironmentDepthMode environmentDepthMode) => throw new System.NotImplementedException(k_ExceptionMsg); public static EnvironmentDepthMode UnityARKit_OcclusionProvider_GetCurrentEnvironmentDepthMode() => throw new NotImplementedException(k_ExceptionMsg); public static bool UnityARKit_OcclusionProvider_TryGetHumanStencil( out XRTextureDescriptor humanStencilDescriptor) => throw new NotImplementedException(k_ExceptionMsg); public static bool UnityARKit_OcclusionProvider_TryGetHumanDepth( out XRTextureDescriptor humanDepthDescriptor) => throw new NotImplementedException(k_ExceptionMsg); public static bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepth( out XRTextureDescriptor envDepthDescriptor) => throw new NotImplementedException(k_ExceptionMsg); public static bool UnityARKit_OcclusionProvider_TryGetEnvironmentDepthConfidence( out XRTextureDescriptor envDepthConfidenceDescriptor) => throw new NotImplementedException(k_ExceptionMsg); public static unsafe void* UnityARKit_OcclusionProvider_AcquireTextureDescriptors( out int length, out int elementSize) => throw new NotImplementedException(k_ExceptionMsg); public static unsafe void UnityARKit_OcclusionProvider_ReleaseTextureDescriptors(void* descriptors) => throw new NotImplementedException(k_ExceptionMsg); public static bool UnityARKit_OcclusionProvider_IsHumanEnabled() => false; public static bool UnityARKit_OcclusionProvider_IsEnvironmentEnabled() => false; public static Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationStencil() => Supported.Unsupported; public static Supported UnityARKit_OcclusionProvider_DoesSupportBodySegmentationDepth() => Supported.Unsupported; public static Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepth() => Supported.Unsupported; public static Supported UnityARKit_OcclusionProvider_DoesSupportEnvironmentDepthTemporalSmoothing() => Supported.Unsupported; public static bool UnityARKit_OcclusionProvider_GetEnvironmentDepthTemporalSmoothingEnabled() => false; #endif } } }