Ejemplo n.º 1
0
        /// <summary>
        /// Creates and returns a new <see cref="VolumeStack"/> to use when you need to store
        /// the result of the Volume blending pass in a separate stack.
        /// </summary>
        /// <returns></returns>
        /// <seealso cref="VolumeStack"/>
        /// <seealso cref="Update(VolumeStack,Transform,LayerMask)"/>
        public VolumeStack CreateStack()
        {
            var stack = new VolumeStack();

            stack.Reload(baseComponentTypes);
            return(stack);
        }
Ejemplo n.º 2
0
        // Go through all listed components and lerp overridden values in the global state
        void OverrideData(VolumeStack stack, List <VolumeComponent> components, float interpFactor)
        {
            foreach (var component in components)
            {
                if (!component.active)
                {
                    continue;
                }

                var state = stack.GetComponent(component.GetType());
                component.Override(state, interpFactor);
            }
        }
Ejemplo n.º 3
0
        // Faster version of OverrideData to force replace values in the global state
        void ReplaceData(VolumeStack stack, List <VolumeComponent> components)
        {
            foreach (var component in components)
            {
                var target = stack.GetComponent(component.GetType());
                int count  = component.parameters.Count;

                for (int i = 0; i < count; i++)
                {
                    target.parameters[i].SetValue(component.parameters[i]);
                }
            }
        }
Ejemplo n.º 4
0
        public void CheckStack(VolumeStack stack)
        {
            // The editor doesn't reload the domain when exiting play mode but still kills every
            // object created while in play mode, like stacks' component states
            var components = stack.components;

            if (components == null)
            {
                stack.Reload(baseComponentTypes);
                return;
            }

            foreach (var kvp in components)
            {
                if (kvp.Key == null || kvp.Value == null)
                {
                    stack.Reload(baseComponentTypes);
                    return;
                }
            }
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Destroy a Volume Stack
 /// </summary>
 /// <param name="stack">Volume Stack that needs to be destroyed.</param>
 public void DestroyStack(VolumeStack stack)
 {
     stack.Dispose();
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Updates the Volume manager and stores the result in a custom <see cref="VolumeStack"/>.
        /// </summary>
        /// <param name="stack">The stack to store the blending result into.</param>
        /// <param name="trigger">A reference Transform to consider for positional Volume blending.
        /// </param>
        /// <param name="layerMask">The LayerMask that Unity uses to filter Volumes that it should consider
        /// for blending.</param>
        /// <seealso cref="VolumeStack"/>
        public void Update(VolumeStack stack, Transform trigger, LayerMask layerMask)
        {
            Assert.IsNotNull(stack);

            CheckBaseTypes();
            CheckStack(stack);

            // Start by resetting the global state to default values
            ReplaceData(stack, m_ComponentsDefaultState);

            bool onlyGlobal = trigger == null;
            var  triggerPos = onlyGlobal ? Vector3.zero : trigger.position;

            // Sort the cached volume list(s) for the given layer mask if needed and return it
            var volumes = GrabVolumes(layerMask);

            Camera camera = null;

            // Behavior should be fine even if camera is null
            if (!onlyGlobal)
            {
                trigger.TryGetComponent <Camera>(out camera);
            }

#if UNITY_EDITOR
            // requested or prefab isolation mode.
            bool needIsolation = needIsolationFilteredByRenderer || (UnityEditor.SceneManagement.StageUtility.GetCurrentStageHandle() != UnityEditor.SceneManagement.StageUtility.GetMainStageHandle());
#endif

            // Traverse all volumes
            foreach (var volume in volumes)
            {
#if UNITY_EDITOR
                // Skip volumes that aren't in the scene currently displayed in the scene view
                if (needIsolation &&
                    !IsVolumeRenderedByCamera(volume, camera))
                {
                    continue;
                }
#endif

                // Skip disabled volumes and volumes without any data or weight
                if (!volume.enabled || volume.profileRef == null || volume.weight <= 0f)
                {
                    continue;
                }

                // Global volumes always have influence
                if (volume.isGlobal)
                {
                    OverrideData(stack, volume.profileRef.components, Mathf.Clamp01(volume.weight));
                    continue;
                }

                if (onlyGlobal)
                {
                    continue;
                }

                // If volume isn't global and has no collider, skip it as it's useless
                var colliders = m_TempColliders;
                volume.GetComponents(colliders);
                if (colliders.Count == 0)
                {
                    continue;
                }

                // Find closest distance to volume, 0 means it's inside it
                float closestDistanceSqr = float.PositiveInfinity;

                foreach (var collider in colliders)
                {
                    if (!collider.enabled)
                    {
                        continue;
                    }

                    var closestPoint = collider.ClosestPoint(triggerPos);
                    var d            = (closestPoint - triggerPos).sqrMagnitude;

                    if (d < closestDistanceSqr)
                    {
                        closestDistanceSqr = d;
                    }
                }

                colliders.Clear();
                float blendDistSqr = volume.blendDistance * volume.blendDistance;

                // Volume has no influence, ignore it
                // Note: Volume doesn't do anything when `closestDistanceSqr = blendDistSqr` but we
                //       can't use a >= comparison as blendDistSqr could be set to 0 in which case
                //       volume would have total influence
                if (closestDistanceSqr > blendDistSqr)
                {
                    continue;
                }

                // Volume has influence
                float interpFactor = 1f;

                if (blendDistSqr > 0f)
                {
                    interpFactor = 1f - (closestDistanceSqr / blendDistSqr);
                }

                // No need to clamp01 the interpolation factor as it'll always be in [0;1[ range
                OverrideData(stack, volume.profileRef.components, interpFactor * Mathf.Clamp01(volume.weight));
            }
        }
Ejemplo n.º 7
0
        // Update a specific stack - can be used to manage your own stack and store it for later use
        public void Update(VolumeStack stack, Transform trigger, LayerMask layerMask)
        {
            Assert.IsNotNull(stack);

            CheckBaseTypes();
            CheckStack(stack);

            // Start by resetting the global state to default values
            ReplaceData(stack, m_ComponentsDefaultState);

            bool onlyGlobal = trigger == null;
            var  triggerPos = onlyGlobal ? Vector3.zero : trigger.position;

            // Sort the cached volume list(s) for the given layer mask if needed and return it
            var volumes = GrabVolumes(layerMask);

            // Traverse all volumes
            foreach (var volume in volumes)
            {
                // Skip disabled volumes and volumes without any data or weight
                if (!volume.enabled || volume.profileRef == null || volume.weight <= 0f)
                {
                    continue;
                }

                // Global volumes always have influence
                if (volume.isGlobal)
                {
                    OverrideData(stack, volume.profileRef.components, Mathf.Clamp01(volume.weight));
                    continue;
                }

                if (onlyGlobal)
                {
                    continue;
                }

                // If volume isn't global and has no collider, skip it as it's useless
                var colliders = m_TempColliders;
                volume.GetComponents(colliders);
                if (colliders.Count == 0)
                {
                    continue;
                }

                // Find closest distance to volume, 0 means it's inside it
                float closestDistanceSqr = float.PositiveInfinity;

                foreach (var collider in colliders)
                {
                    if (!collider.enabled)
                    {
                        continue;
                    }

                    var closestPoint = collider.ClosestPoint(triggerPos);
                    var d            = (closestPoint - triggerPos).sqrMagnitude;

                    if (d < closestDistanceSqr)
                    {
                        closestDistanceSqr = d;
                    }
                }

                colliders.Clear();
                float blendDistSqr = volume.blendDistance * volume.blendDistance;

                // Volume has no influence, ignore it
                // Note: Volume doesn't do anything when `closestDistanceSqr = blendDistSqr` but we
                //       can't use a >= comparison as blendDistSqr could be set to 0 in which case
                //       volume would have total influence
                if (closestDistanceSqr > blendDistSqr)
                {
                    continue;
                }

                // Volume has influence
                float interpFactor = 1f;

                if (blendDistSqr > 0f)
                {
                    interpFactor = 1f - (closestDistanceSqr / blendDistSqr);
                }

                // No need to clamp01 the interpolation factor as it'll always be in [0;1[ range
                OverrideData(stack, volume.profileRef.components, interpFactor * Mathf.Clamp01(volume.weight));
            }
        }