using System;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine.SubsystemsImplementation;
namespace UnityEngine.XR.ARSubsystems
{
///
/// Provides access to a device's camera.
///
///
/// The XRCameraSubsystem links a Unity Camera to a device camera for video overlay (pass-thru
/// rendering). It also allows developers to query for environmental light estimation if available.
///
public class XRCameraSubsystem : SubsystemWithProvider
{
///
/// Interface for providing camera functionality for the implementation.
///
public class Provider : SubsystemProvider
{
///
/// An instance of the used to operate on objects.
///
public virtual XRCpuImage.Api cpuImageApi => null;
///
/// Get the Material used by this to render the camera texture.
///
/// The Material to render the camera texture.
public virtual Material cameraMaterial => null;
///
/// Get whether camera permission has been granted.
///
/// if camera permission has been granted. Otherwise, .
public virtual bool permissionGranted => false;
///
/// Get whether culling should be inverted during rendering. Some front-facing camera modes might
/// require this.
///
/// if culling should be inverted during rendering. Otherwise, .
public virtual bool invertCulling => false;
///
/// Get the actual camera facing direction.
///
/// The current camera facing direction.
///
public virtual Feature currentCamera => Feature.None;
///
/// Get or set the requested camera facing direction, that is, the bits.
///
/// The requested camera facing direction.
public virtual Feature requestedCamera
{
get => Feature.None;
set { }
}
///
/// Get whether auto focus is enabled.
///
/// if auto focus is enabled. Otherwise, .
///
public virtual bool autoFocusEnabled => false;
///
/// Get or set whether auto focus is requested.
///
/// if auto focus is requested. Otherwise, .
public virtual bool autoFocusRequested
{
get => false;
set { }
}
///
/// Get whether Image Stabilization is enabled.
///
/// if EIS is enabled. Otherwise, .
///
public virtual bool imageStabilizationEnabled => false;
///
/// Get or set whether Image Stabilization is requested.
///
/// if EIS is requested. Otherwise, .
public virtual bool imageStabilizationRequested
{
get => false;
set { }
}
///
/// Get whether the current session configuration allows the camera torch to be turned on or off.
///
/// true if supported.
public virtual bool DoesCurrentCameraSupportTorch()
{
return false;
}
///
/// Gets the current camera torch mode
///
/// The current .
public virtual XRCameraTorchMode currentCameraTorchMode
{
get => XRCameraTorchMode.Off;
}
///
/// Get or set the requested camera torch mode.
///
/// if the torch is requested to be on. Otherwise, .
public virtual XRCameraTorchMode requestedCameraTorchMode
{
get => XRCameraTorchMode.Off;
set { }
}
///
/// Get the current light estimation mode in use by the subsystem.
///
/// The current light estimation mode.
///
public virtual Feature currentLightEstimation => Feature.None;
///
/// Get or set the requested light estimation mode.
///
/// The requested light estimation mode.
public virtual Feature requestedLightEstimation
{
get => Feature.None;
set { }
}
///
/// Property to be implemented by the provider to query or set the current camera configuration.
///
/// The current camera configuration, if it exists. Otherwise, .
/// Thrown when setting the current configuration if the
/// implementation does not support camera configurations.
/// Thrown when setting the current configuration if the given
/// configuration is not a valid, supported camera configuration.
/// Thrown when setting the current configuration if the
/// implementation is unable to set the current camera configuration.
public virtual XRCameraConfiguration? currentConfiguration
{
get => null;
set => throw new NotSupportedException("setting current camera configuration is not supported by this implementation");
}
///
/// Get the current .
///
/// The current .
///
public virtual XRCameraBackgroundRenderingMode currentBackgroundRenderingMode => XRCameraBackgroundRenderingMode.None;
///
/// Get or set the requested .
///
/// The requested background rendering mode.
public virtual XRSupportedCameraBackgroundRenderingMode requestedBackgroundRenderingMode
{
get => XRSupportedCameraBackgroundRenderingMode.Any;
set { }
}
///
/// Get the supported s defined as s.
///
/// The supported background rendering modes.
public virtual XRSupportedCameraBackgroundRenderingMode supportedBackgroundRenderingMode => XRSupportedCameraBackgroundRenderingMode.None;
///
/// Attempts to get the platform specific rendering parameters for rendering the camera background texture.
///
/// The platform specific rendering parameters for rendering the camera background texture.
/// if the platform provides specialized rendering parameters. Otherwise, .
public virtual bool TryGetRenderingParameters(out XRCameraBackgroundRenderingParams cameraBackgroundRenderingParameters)
{
cameraBackgroundRenderingParameters = default;
return false;
}
///
/// Start the camera for the subsystem.
///
public override void Start() { }
///
/// Stop the camera for the subsystem.
///
public override void Stop() { }
///
/// Destroy the camera for the subsystem.
///
public override void Destroy() { }
///
/// Get the camera frame for the subsystem.
///
/// The current Unity Camera parameters.
/// The current camera frame returned by the method.
/// if the method successfully got a frame. Otherwise, .
public virtual bool TryGetFrame(
XRCameraParams cameraParams,
out XRCameraFrame cameraFrame)
{
cameraFrame = default;
return false;
}
///
/// Get the camera intrinsics information.
///
/// The camera intrinsics information returned from the method.
/// if the method successfully gets the camera intrinsics information.
/// Otherwise, .
public virtual bool TryGetIntrinsics(
out XRCameraIntrinsics cameraIntrinsics)
{
cameraIntrinsics = default(XRCameraIntrinsics);
return false;
}
///
/// Get the supported camera configurations.
///
/// A default value used to fill the returned array before copying in
/// real values. This ensures future additions to this are backwards compatible.
/// The allocation strategy to use for the returned data.
/// The supported camera configurations.
public virtual NativeArray GetConfigurations(
XRCameraConfiguration defaultCameraConfiguration,
Allocator allocator)
{
return new NativeArray(0, allocator);
}
///
/// Get the s associated with the current .
///
/// A default value used to fill the returned array before copying in real
/// values. This ensures future additions to this are backwards compatible.
/// The allocation strategy to use for the returned data..
/// The current texture descriptors.
public virtual NativeArray GetTextureDescriptors(
XRTextureDescriptor defaultDescriptor,
Allocator allocator)
{
return new NativeArray(0, allocator);
}
///
/// Get the enabled and disabled shader keywords for the Material.
///
/// The keywords to enable for the Material.
/// The keywords to disable for the Material.
[Obsolete("GetMaterialKeywords(out List, out List) has been deprecated in AR Foundation version 6.0. Use GetShaderKeywords2 instead.")]
public virtual void GetMaterialKeywords(out List enabledKeywords, out List disabledKeywords)
{
enabledKeywords = null;
disabledKeywords = null;
}
///
/// Get the enabled and disabled shader keywords for the Material.
///
/// Returns an with the enabled and disabled shader keywords for the Material.
[Obsolete("GetShaderKeywords is deprecated as of AR Foundation 6.1. Use GetShaderKeywords2 instead.")]
public virtual ShaderKeywords GetShaderKeywords() => default;
///
/// Get the shader keywords that are enabled or disabled by the provider.
///
/// The enabled and disabled shader keywords.
public virtual XRShaderKeywords GetShaderKeywords2() => default;
///
/// Get the latest native camera image.
///
/// The metadata required to construct a .
/// if the camera image is acquired. Otherwise, .
/// Thrown if the implementation does not support camera image.
public virtual bool TryAcquireLatestCpuImage(out XRCpuImage.Cinfo cameraImageCinfo)
{
throw new NotSupportedException("getting camera image is not supported by this implementation");
}
///
/// Create the camera material from the given camera shader name.
///
/// The name of the camera shader.
/// The created camera material shader.
/// Thrown if the shader cannot be found or if a material
/// cannot be created for the shader.
protected Material CreateCameraMaterial(string cameraShaderName)
{
var shader = Shader.Find(cameraShaderName);
if (shader == null)
{
throw new InvalidOperationException(
$"Could not find shader named '{cameraShaderName}' required "
+ $"for video overlay on camera subsystem.");
}
var material = new Material(shader);
if (material == null)
{
throw new InvalidOperationException(
$"Could not create a material for shader named '{cameraShaderName}' required for video"
+ " overlay on camera subsystem.");
}
return material;
}
///
/// Method to be implemented by the provider to handle any required platform-specific functionality
/// immediately before rendering the camera background. This method will always be called on the render
/// thread and should only be called by the code responsible for executing background rendering on
/// mobile AR platforms.
///
/// Platform-specific identifier.
public virtual void OnBeforeBackgroundRender(int id) {}
}
///
/// Get the camera currently in use.
///
/// The current camera.
public Feature currentCamera => provider.currentCamera.Cameras();
///
/// Get or set the requested camera (that is, the bits).
///
/// The requested camera.
public Feature requestedCamera
{
get => provider.requestedCamera;
set => provider.requestedCamera = value.Cameras();
}
///
/// Get the current .
///
/// The current camera background rendering mode.
///
public XRCameraBackgroundRenderingMode currentCameraBackgroundRenderingMode => permissionGranted
? provider.currentBackgroundRenderingMode
: XRCameraBackgroundRenderingMode.None;
///
/// Get or set the requested .
///
/// The requested camera background rendering mode.
public XRSupportedCameraBackgroundRenderingMode requestedCameraBackgroundRenderingMode
{
get => provider.requestedBackgroundRenderingMode;
set => provider.requestedBackgroundRenderingMode = value;
}
///
/// Get the supported s.
/// Indicates which s are supported.
///
/// The supported camera background rendering modes.
public XRSupportedCameraBackgroundRenderingMode supportedCameraBackgroundRenderingMode =>
provider.supportedBackgroundRenderingMode;
///
/// Indicates whether auto focus is enabled.
///
/// if auto focus is enabled. Otherwise, .
///
public bool autoFocusEnabled => provider.autoFocusEnabled;
///
/// Get or set whether autofocus is requested.
///
/// if autofocus is requested. Otherwise, .
public bool autoFocusRequested
{
get => provider.autoFocusRequested;
set => provider.autoFocusRequested = value;
}
///
/// Indicate whether Image Stabilization is enabled.
///
/// if EIS is enabled. Otherwise, .
///
public bool imageStabilizationEnabled => provider.imageStabilizationEnabled;
///
/// Get or set whether Image Stabilization is requested.
///
/// if EIS is requested. Otherwise, .
public bool imageStabilizationRequested
{
get => provider.imageStabilizationRequested;
set => provider.imageStabilizationRequested = value;
}
///
/// Get or set the requested camera torch mode.
///
/// if the torch is requested to be on. Otherwise, .
public XRCameraTorchMode requestedCameraTorchMode
{
get => provider.requestedCameraTorchMode;
set => provider.requestedCameraTorchMode = value;
}
///
/// Gets the current camera torch mode.
///
/// The camera torch mode.
public XRCameraTorchMode currentCameraTorchMode
{
get => provider.currentCameraTorchMode;
}
///
/// Get whether the current session configuration allows the camera torch to be turned on or off.
///
/// true if supported.
public bool DoesCurrentCameraSupportTorch()
{
return provider.DoesCurrentCameraSupportTorch();
}
///
/// Get the current light estimation mode in use by the provider.
///
/// The current light estimation mode.
///
public Feature currentLightEstimation => provider.currentLightEstimation.LightEstimation();
///
/// Get or set the requested light estimation mode.
///
/// The requested light estimation mode.
public Feature requestedLightEstimation
{
get => provider.requestedLightEstimation.LightEstimation();
set => provider.requestedLightEstimation = value.LightEstimation();
}
///
/// Get the Material used by to render the camera texture.
///
/// The Material to render the camera texture.
public Material cameraMaterial => provider.cameraMaterial;
///
/// Attempts to get the platform specific rendering parameters for rendering the camera background texture.
///
///
/// The platform specific rendering parameters for rendering the camera background texture.
///
///
/// if the platform provides specialized rendering parameters or otherwise.
///
public bool TryGetRenderingParameters(out XRCameraBackgroundRenderingParams cameraBackgroundRenderingParameters)
=> provider.TryGetRenderingParameters(out cameraBackgroundRenderingParameters);
///
/// Indicates whether camera permission has been granted.
///
/// if camera permission has been granted. Otherwise, .
public bool permissionGranted => provider.permissionGranted;
///
/// Set this to to invert the culling mode during rendering. Some front-facing
/// camera modes might require this.
///
public bool invertCulling => provider.invertCulling;
///
/// The current camera configuration.
///
/// The current camera configuration, if it exists. Otherwise, .
/// Thrown when setting the current configuration if the
/// implementation does not support camera configurations.
/// Thrown when setting the current configuration if the given
/// configuration is .
/// Thrown when setting the current configuration if the given
/// configuration is not a supported camera configuration.
/// Thrown when setting the current configuration if the
/// implementation is unable to set the current camera configuration.
///
public virtual XRCameraConfiguration? currentConfiguration
{
get => provider.currentConfiguration;
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value), "cannot set the camera configuration to null");
}
provider.currentConfiguration = value;
}
}
///
/// Construct the .
///
public XRCameraSubsystem() { }
///
/// Gets the s associated with the current frame. The caller owns the returned
/// NativeArray and is responsible for calling Dispose on it.
///
/// An array of texture descriptors.
/// The allocator to use when creating the returned NativeArray.
public NativeArray GetTextureDescriptors(Allocator allocator)
{
return provider.GetTextureDescriptors(default, allocator);
}
///
/// Method to be called on the render thread to handle any required platform-specific functionality
/// immediately before rendering the camera background. This method will always be called on the render
/// thread and should only be called by the code responsible for executing background rendering on
/// mobile AR platforms.
///
/// Platform-specific identifier.
public void OnBeforeBackgroundRender(int id)
{
provider.OnBeforeBackgroundRender(id);
}
///
/// Get the camera intrinsics information.
///
/// The returned camera intrinsics information.
/// if the method successfully gets the camera intrinsics information.
/// Otherwise, .
///
/// > [!NOTE]
/// > The intrinsics may change each frame. You should call this each frame that you need intrinsics
/// > in order to ensure you are using the intrinsics for the current frame.
///
public bool TryGetIntrinsics(out XRCameraIntrinsics cameraIntrinsics)
{
return provider.TryGetIntrinsics(out cameraIntrinsics);
}
///
/// Get the supported camera configurations.
///
/// The allocation strategy to use for the returned data.
/// The supported camera configurations.
public NativeArray GetConfigurations(Allocator allocator)
{
return provider.GetConfigurations(default, allocator);
}
///
/// Get the latest frame from the provider.
///
/// The Unity Camera parameters.
/// The camera frame to be populated if the subsystem is running and successfully provides
/// the latest camera frame.
/// if the camera frame is successfully returned. Otherwise, .
public bool TryGetLatestFrame(XRCameraParams cameraParams, out XRCameraFrame frame)
{
if (running && provider.TryGetFrame(cameraParams, out frame))
{
return true;
}
frame = default;
return false;
}
///
/// Get the enabled and disabled shader keywords for the material.
///
/// The keywords to enable for the material.
/// The keywords to disable for the material.
[Obsolete("GetMaterialKeywords(out List, out List) has been deprecated in AR Foundation version 6.0. Use GetShaderKeywords2 instead.")]
public void GetMaterialKeywords(out List enabledKeywords, out List disabledKeywords)
=> provider.GetMaterialKeywords(out enabledKeywords, out disabledKeywords);
///
/// Get the enabled and disabled shader keywords for the material.
///
/// Returns an with the enabled and disabled shader keywords for the Material.
[Obsolete("GetShaderKeywords is deprecated as of AR Foundation 6.1. Use GetShaderKeywords2 instead.")]
public ShaderKeywords GetShaderKeywords() => provider.GetShaderKeywords();
///
/// Get the shader keywords that are enabled or disabled by the provider.
///
/// The enabled and disabled shader keywords.
public XRShaderKeywords GetShaderKeywords2() => provider.GetShaderKeywords2();
///
/// Attempts to acquire the latest camera image. This provides direct access to the raw pixel data, as well as
/// to utilities to convert to RGB and Grayscale formats.
///
/// A valid if this method returns .
/// if the image was acquired. Otherwise, .
/// Thrown if the implementation does not support camera image.
/// The returned must be disposed to avoid resource leaks.
public bool TryAcquireLatestCpuImage(out XRCpuImage cpuImage)
{
if (provider.cpuImageApi != null && provider.TryAcquireLatestCpuImage(out var cinfo))
{
cpuImage = new XRCpuImage(provider.cpuImageApi, cinfo);
return true;
}
cpuImage = default;
return false;
}
///
/// Registers a camera subsystem implementation based on the given subsystem parameters.
///
/// The parameters defining the camera subsystem functionality implemented
/// by the subsystem provider.
/// if the subsystem implementation is registered. Otherwise, .
/// Thrown when the values specified in the parameter are invalid.
/// Typically, this happens when required parameters are or empty
/// or types that do not derive from the required base class.
///
[Obsolete("XRCameraSubsystem.Register(XRCameraSubsystemCinfo) has been deprecated in AR Foundation version 6.0. Use XRCameraSubsystemDescriptor.Register(XRCameraSubsystemDescriptor.Cinfo) instead.")]
public static bool Register(XRCameraSubsystemCinfo cameraSubsystemParams)
{
var cameraSubsystemCinfo = new XRCameraSubsystemDescriptor.Cinfo
{
id = cameraSubsystemParams.id,
providerType = cameraSubsystemParams.providerType,
subsystemTypeOverride = cameraSubsystemParams.subsystemTypeOverride,
supportsAverageBrightness = cameraSubsystemParams.supportsAverageBrightness,
supportsAverageColorTemperature = cameraSubsystemParams.supportsAverageColorTemperature,
supportsColorCorrection = cameraSubsystemParams.supportsColorCorrection,
supportsDisplayMatrix = cameraSubsystemParams.supportsDisplayMatrix,
supportsProjectionMatrix = cameraSubsystemParams.supportsProjectionMatrix,
supportsTimestamp = cameraSubsystemParams.supportsTimestamp,
supportsCameraConfigurations = cameraSubsystemParams.supportsCameraConfigurations,
supportsCameraImage = cameraSubsystemParams.supportsCameraImage,
supportsAverageIntensityInLumens = cameraSubsystemParams.supportsAverageIntensityInLumens,
supportsFocusModes = cameraSubsystemParams.supportsFocusModes,
supportsFaceTrackingAmbientIntensityLightEstimation = cameraSubsystemParams.supportsFaceTrackingAmbientIntensityLightEstimation,
supportsFaceTrackingHDRLightEstimation = cameraSubsystemParams.supportsFaceTrackingHDRLightEstimation,
supportsWorldTrackingAmbientIntensityLightEstimation = cameraSubsystemParams.supportsWorldTrackingAmbientIntensityLightEstimation,
supportsWorldTrackingHDRLightEstimation = cameraSubsystemParams.supportsWorldTrackingHDRLightEstimation,
supportsCameraGrain = cameraSubsystemParams.supportsCameraGrain,
supportsImageStabilizationDelegate = cameraSubsystemParams.supportsImageStabilizationDelegate,
supportsExifData = cameraSubsystemParams.supportsExifData,
};
XRCameraSubsystemDescriptor.Register(cameraSubsystemCinfo);
return true;
}
}
}