using System; namespace UnityEngine.Rendering.Universal { /// Light Layers. [Flags] public enum LightLayerEnum { /// The light will no affect any object. Nothing = 0, // Custom name for "Nothing" option /// Light Layer 0. LightLayerDefault = 1 << 0, /// Light Layer 1. LightLayer1 = 1 << 1, /// Light Layer 2. LightLayer2 = 1 << 2, /// Light Layer 3. LightLayer3 = 1 << 3, /// Light Layer 4. LightLayer4 = 1 << 4, /// Light Layer 5. LightLayer5 = 1 << 5, /// Light Layer 6. LightLayer6 = 1 << 6, /// Light Layer 7. LightLayer7 = 1 << 7, /// Everything. Everything = 0xFF, // Custom name for "Everything" option } /// /// Contains extension methods for Light class. /// public static class LightExtensions { /// /// Universal Render Pipeline exposes additional light data in a separate component. /// This method returns the additional data component for the given light or create one if it doesn't exist yet. /// /// /// The UniversalAdditionalLightData for this light. /// public static UniversalAdditionalLightData GetUniversalAdditionalLightData(this Light light) { var gameObject = light.gameObject; bool componentExists = gameObject.TryGetComponent(out var lightData); if (!componentExists) lightData = gameObject.AddComponent(); return lightData; } } /// /// Class containing various additional light data used by URP. /// [DisallowMultipleComponent] [RequireComponent(typeof(Light))] [URPHelpURL("universal-additional-light-data")] public class UniversalAdditionalLightData : MonoBehaviour, ISerializationCallbackReceiver, IAdditionalData { // Version 0 means serialized data before the version field. [SerializeField] int m_Version = 3; internal int version { get => m_Version; } [Tooltip("Controls if light Shadow Bias parameters use pipeline settings.")] [SerializeField] bool m_UsePipelineSettings = true; /// /// Controls if light Shadow Bias parameters use pipeline settings or not. /// public bool usePipelineSettings { get { return m_UsePipelineSettings; } set { m_UsePipelineSettings = value; } } /// /// Value used to indicate custom shadow resolution tier for additional lights. /// public static readonly int AdditionalLightsShadowResolutionTierCustom = -1; /// /// Value used to indicate low shadow resolution tier for additional lights. /// public static readonly int AdditionalLightsShadowResolutionTierLow = 0; /// /// Value used to indicate medium shadow resolution tier for additional lights. /// public static readonly int AdditionalLightsShadowResolutionTierMedium = 1; /// /// Value used to indicate high shadow resolution tier for additional lights. /// public static readonly int AdditionalLightsShadowResolutionTierHigh = 2; /// /// The default shadow resolution tier for additional lights. /// public static readonly int AdditionalLightsShadowDefaultResolutionTier = AdditionalLightsShadowResolutionTierHigh; /// /// The default custom shadow resolution for additional lights. /// public static readonly int AdditionalLightsShadowDefaultCustomResolution = 128; [NonSerialized] private Light m_Light; /// /// Returns the cached light component associated with the game object that owns this light data. /// #if UNITY_EDITOR internal new Light light #else internal Light light #endif { get { if (!m_Light) TryGetComponent(out m_Light); return m_Light; } } /// /// The minimum shadow resolution for additional lights. /// public static readonly int AdditionalLightsShadowMinimumResolution = 128; [Tooltip("Controls if light shadow resolution uses pipeline settings.")] [SerializeField] int m_AdditionalLightsShadowResolutionTier = AdditionalLightsShadowDefaultResolutionTier; /// /// Returns the selected shadow resolution tier. /// public int additionalLightsShadowResolutionTier { get { return m_AdditionalLightsShadowResolutionTier; } } // The layer(s) this light belongs too. [Obsolete("This is obsolete, please use m_RenderingLayerMask instead.", false)] [SerializeField] LightLayerEnum m_LightLayerMask = LightLayerEnum.LightLayerDefault; /// /// The layer(s) this light belongs to. /// [Obsolete("This is obsolete, please use renderingLayerMask instead.", true)] public LightLayerEnum lightLayerMask { get { return m_LightLayerMask; } set { m_LightLayerMask = value; } } [SerializeField] uint m_RenderingLayers = 1; /// /// Specifies which rendering layers this light will affect. /// public uint renderingLayers { get { return m_RenderingLayers; } set { if (m_RenderingLayers != value) { m_RenderingLayers = value; SyncLightAndShadowLayers(); } } } [SerializeField] bool m_CustomShadowLayers = false; /// /// Indicates whether shadows need custom layers. /// If not, then it uses the same settings as lightLayerMask. /// public bool customShadowLayers { get { return m_CustomShadowLayers; } set { if (m_CustomShadowLayers != value) { m_CustomShadowLayers = value; SyncLightAndShadowLayers(); } } } // The layer(s) used for shadow casting. [SerializeField] LightLayerEnum m_ShadowLayerMask = LightLayerEnum.LightLayerDefault; /// /// The layer(s) for shadow. /// [Obsolete("This is obsolete, please use shadowRenderingLayerMask instead.", true)] public LightLayerEnum shadowLayerMask { get { return m_ShadowLayerMask; } set { m_ShadowLayerMask = value; } } [SerializeField] uint m_ShadowRenderingLayers = 1; /// /// Specifies which rendering layers this light shadows will affect. /// public uint shadowRenderingLayers { get { return m_ShadowRenderingLayers; } set { if (value != m_ShadowRenderingLayers) { m_ShadowRenderingLayers = value; SyncLightAndShadowLayers(); } } } /// /// Controls the size of the cookie mask currently assigned to the light. /// [Tooltip("Controls the size of the cookie mask currently assigned to the light.")] public Vector2 lightCookieSize { get => m_LightCookieSize; set => m_LightCookieSize = value; } [SerializeField] Vector2 m_LightCookieSize = Vector2.one; /// /// Controls the offset of the cookie mask currently assigned to the light. /// [Tooltip("Controls the offset of the cookie mask currently assigned to the light.")] public Vector2 lightCookieOffset { get => m_LightCookieOffset; set => m_LightCookieOffset = value; } [SerializeField] Vector2 m_LightCookieOffset = Vector2.zero; /// /// Light soft shadow filtering quality. /// [Tooltip("Controls the filtering quality of soft shadows. Higher quality has lower performance.")] public SoftShadowQuality softShadowQuality { get => m_SoftShadowQuality; set => m_SoftShadowQuality = value; } [SerializeField] private SoftShadowQuality m_SoftShadowQuality = SoftShadowQuality.UsePipelineSettings; /// public void OnBeforeSerialize() { } /// public void OnAfterDeserialize() { if (m_Version < 2) { #pragma warning disable 618 // Obsolete warning m_RenderingLayers = (uint)m_LightLayerMask; m_ShadowRenderingLayers = (uint)m_ShadowLayerMask; #pragma warning restore 618 // Obsolete warning m_Version = 2; } if (m_Version < 3) { // SoftShadowQuality.UsePipelineSettings added at index 0. Bump existing serialized values by 1. e.g. Low(0) -> Low(1). m_SoftShadowQuality = (SoftShadowQuality)(Math.Clamp((int)m_SoftShadowQuality + 1, 0, (int)SoftShadowQuality.High)); m_Version = 3; } } private void SyncLightAndShadowLayers() { if (light) light.renderingLayerMask = m_CustomShadowLayers ? (int)m_ShadowRenderingLayers : (int)m_RenderingLayers; } } }