using System; using UnityEngine.Rendering; using UnityEngine.XR.ARSubsystems; using Object = UnityEngine.Object; namespace UnityEngine.XR.ARFoundation { /// /// A GameObject component to manage the reflection probe settings as the environment probe changes are applied. /// [RequireComponent(typeof(ReflectionProbe))] [DisallowMultipleComponent] [DefaultExecutionOrder(ARUpdateOrder.k_EnvironmentProbe)] [HelpURL(HelpUrls.ApiWithNamespace + nameof(AREnvironmentProbe) + ".html")] public class AREnvironmentProbe : ARTrackable { /// /// The reflection probe component attached to the GameObject. /// /// /// The reflection probe component attached to the GameObject. /// ReflectionProbe m_ReflectionProbe; /// /// The current environment texture data wrapping the reflection probe environment texture. /// /// /// The current environment texture data wrapping the reflection probe environment texture. /// XRTextureDescriptor m_CurrentTextureDescriptor; /// /// The texture info of the custom baked texture from the reflection probe. /// /// /// The texture info of the custom baked texture from the reflection probe. /// ARTextureInfo m_CustomBakedTextureInfo; /// /// Specifies the texture filter mode to be used with the environment texture. /// /// /// The texture filter mode to be used with the environment texture. /// public FilterMode environmentTextureFilterMode { get => m_EnvironmentTextureFilterMode; set { m_EnvironmentTextureFilterMode = value; if ((m_ReflectionProbe != null) && (m_ReflectionProbe.customBakedTexture != null)) { m_ReflectionProbe.customBakedTexture.filterMode = m_EnvironmentTextureFilterMode; } } } FilterMode m_EnvironmentTextureFilterMode = FilterMode.Trilinear; /// /// The placement type (for example, manual or automatic). If manual, this probe was created by . /// public AREnvironmentProbePlacementType placementType { get; internal set; } /// /// The size (dimensions) of the environment probe. /// public Vector3 size => sessionRelativeData.size; /// /// The extents of the environment probe. This is always half the . /// public Vector3 extents => size * .5f; /// /// A native pointer associated with this environment probe. /// The data pointed to by this pointer is implementation defined. /// While the lifetime is also implementation defined, it should be valid at /// least until the next frame. /// public IntPtr nativePtr => sessionRelativeData.nativePtr; /// /// The XRTextureDescriptor associated with this environment probe. This is used to generate the cubemap texture on the reflection probe component. /// public XRTextureDescriptor textureDescriptor => m_CurrentTextureDescriptor; /// /// Initializes the GameObject transform and reflection probe component from the scene. /// void Awake() { m_ReflectionProbe = GetComponent(); // Set the reflection probe mode to use a custom baked texture. m_ReflectionProbe.mode = ReflectionProbeMode.Custom; } Transform GetTrackablesParent() { if (AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager) { return manager.GetComponent().trackablesParent; } return null; } internal protected override void OnAfterSetSessionRelativeData() { var trackablesParent = GetTrackablesParent(); if (trackablesParent && transform.parent != trackablesParent) { var pose = sessionRelativeData.pose; // Compute the desired world space transform matrix for the environment probe var desiredLocalToWorld = trackablesParent.localToWorldMatrix * Matrix4x4.TRS(pose.position, pose.rotation, sessionRelativeData.scale); if (transform.parent) { // If the probe has a parent (i.e., it is not at the root), then we need to compute // its localScale such that its final world-space scale will match what it would be // if it were under the ARSessionOrigin. var localToParent = transform.parent.worldToLocalMatrix * desiredLocalToWorld; transform.localScale = localToParent.lossyScale; } else { // Otherwise, it is at the scene root, so just set its localScale is its world-space scale. transform.localScale = desiredLocalToWorld.lossyScale; } } else { transform.localScale = sessionRelativeData.scale; } // Update the environment texture if the environment texture is valid. m_ReflectionProbe.enabled = sessionRelativeData.textureDescriptor.valid; if (sessionRelativeData.textureDescriptor.valid) { UpdateEnvironmentTexture(sessionRelativeData.textureDescriptor); } // Update the reflection probe box. m_ReflectionProbe.center = Vector3.zero; m_ReflectionProbe.size = sessionRelativeData.size; m_ReflectionProbe.boxProjection = !float.IsInfinity(m_ReflectionProbe.size.x); // Manual placement is set by the manager. Unknown means it must have been added automatically. if (placementType == AREnvironmentProbePlacementType.Unknown) { placementType = AREnvironmentProbePlacementType.Automatic; } } /// /// Applies the texture data in the XRTextureDescriptor to the reflection probe settings. /// /// The environment texture data to apply to the reflection probe baked /// texture. void UpdateEnvironmentTexture(XRTextureDescriptor textureDescriptor) { if(m_ReflectionProbe.customBakedTexture == null) { m_CustomBakedTextureInfo = new ARTextureInfo(textureDescriptor); } else { m_CustomBakedTextureInfo = ARTextureInfo.GetUpdatedTextureInfo(m_CustomBakedTextureInfo, textureDescriptor); } m_CustomBakedTextureInfo.texture.filterMode = m_EnvironmentTextureFilterMode; m_ReflectionProbe.customBakedTexture = m_CustomBakedTextureInfo.texture as Cubemap; // Update the current environment texture metadata. m_CurrentTextureDescriptor = textureDescriptor; } /// /// Generates a string representation of this . /// /// A string representation of this . public override string ToString() => $"{name} [trackableId:{trackableId.ToString()}]"; void OnEnable() { if (AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager) { manager.TryAddEnvironmentProbe(this); } else { pending = true; } } void Update() { if (trackableId.Equals(TrackableId.invalidId) && AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager) { manager.TryAddEnvironmentProbe(this); } } void OnDisable() { if (AREnvironmentProbeManager.instance is AREnvironmentProbeManager manager) { manager.TryRemoveEnvironmentProbe(this); } } } }