using System; using System.Collections.Generic; namespace UnityEngine.Rendering { /// /// Represents the state of a Volume blending update within the Volume system. /// /// /// /// This class is responsible for storing the blending of Volume components across multiple scenes and cameras, /// By default, a global volume stack is provided by the to handle the blending of Volume data across your project. /// This global stack simplifies managing and blending volume data at a project-wide level. However, if you require more granular control over /// the blending process or want to store and manage the blending results separately (e.g., per camera or scene), you can create custom volume /// stacks using . /// The blending of volumes is based on a combination of several factors: /// - **Volume Weight:** Determines how strongly a particular volume influences the final result. /// - **Volume Parameters:** These can be visual settings such as post-processing effects, lighting adjustments, or other specialized effects defined /// in the Volume components. /// - **Camera Volume Stack:** Volume blending can vary per camera, allowing different volumes to be blended for different camera views or scenes. /// /// While the default global volume stack works for most use cases, custom stacks provide greater flexibility and control, allowing developers /// to manage and store volume blending results at a per-scene or per-camera level. This can be particularly useful in complex rendering setups /// or when you want to apply different volume blends for different gameplay contexts or visual effects. /// /// Keep in mind that frequent updates to the volume blending process (e.g., every frame) may have an impact on performance, especially when /// dealing with large numbers of volumes or complex blending operations. /// /// /// /// /// public sealed class VolumeStack : IDisposable { // Holds the state of _all_ component types you can possibly add on volumes internal readonly Dictionary components = new(); // Flat list of every volume parameter for faster per-frame stack reset. internal VolumeParameter[] parameters; // Flag indicating that some properties have received overrides, therefore they must be reset in the next update. internal bool requiresReset = true; // Flag indicating that default state has changed, therefore all properties in the stack must be reset in the next update. internal bool requiresResetForAllProperties = true; internal VolumeStack() { } internal void Clear() { foreach (var component in components) CoreUtils.Destroy(component.Value); components.Clear(); parameters = null; } internal void Reload(Type[] componentTypes) { Clear(); requiresReset = true; requiresResetForAllProperties = true; List parametersList = new(); foreach (var type in componentTypes) { var component = (VolumeComponent)ScriptableObject.CreateInstance(type); components.Add(type, component); parametersList.AddRange(component.parameters); } parameters = parametersList.ToArray(); isValid = true; } /// /// Gets the current state of the of type /// in the stack. /// /// A type of . /// The current state of the of type /// in the stack. public T GetComponent() where T : VolumeComponent { var comp = GetComponent(typeof(T)); return (T)comp; } /// /// Gets the current state of the of the specified type in the /// stack. /// /// The type of to look for. /// The current state of the of the specified type, /// or null if the type is invalid. public VolumeComponent GetComponent(Type type) { components.TryGetValue(type, out var comp); return comp; } /// /// Cleans up the content of this stack. Once a VolumeStack is disposed, it shouldn't /// be used anymore. /// public void Dispose() { Clear(); isValid = false; } /// /// Check if the stack is in valid state and can be used. /// public bool isValid { get; private set; } } }