Rasagar/Library/PackageCache/com.unity.render-pipelines.high-definition/Runtime/Sky/SkySettings.cs
2024-08-26 23:07:20 +03:00

279 lines
13 KiB
C#

using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace UnityEngine.Rendering.HighDefinition
{
/// <summary>
/// This attribute is used to associate a unique ID to a sky class.
/// This is needed to be able to automatically register sky classes and avoid collisions and refactoring class names causing data compatibility issues.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class SkyUniqueID : Attribute
{
internal readonly int uniqueID;
/// <summary>
/// Attribute SkyUniqueID constructor.
/// </summary>
/// <param name="uniqueID">Sky unique ID. Needs to be different from all other registered unique IDs.</param>
public SkyUniqueID(int uniqueID)
{
this.uniqueID = uniqueID;
}
}
/// <summary>
/// Environment Update volume parameter.
/// </summary>
[Serializable, DebuggerDisplay(k_DebuggerDisplay)]
public sealed class EnvUpdateParameter : VolumeParameter<EnvironmentUpdateMode>
{
/// <summary>
/// Environment Update parameter constructor.
/// </summary>
/// <param name="value">Environment Update Mode parameter.</param>
/// <param name="overrideState">Initial override state.</param>
public EnvUpdateParameter(EnvironmentUpdateMode value, bool overrideState = false)
: base(value, overrideState) { }
}
/// <summary>
/// Sky Intensity Mode.
/// </summary>
public enum SkyIntensityMode
{
/// <summary>Intensity is expressed as an exposure.</summary>
Exposure,
/// <summary>Intensity is expressed in lux.</summary>
Lux,
/// <summary>Intensity is expressed as a multiplier.</summary>
Multiplier,
}
/// <summary>
/// Backplate Type for HDRISKy.
/// </summary>
public enum BackplateType
{
/// <summary>Shape of backplate is a Disc.</summary>
Disc,
/// <summary>Shape of backplate is a Rectangle.</summary>
Rectangle,
/// <summary>Shape of backplate is a Ellispe.</summary>
Ellipse,
/// <summary>Shape of backplate is a Infinite Plane.</summary>
Infinite
}
/// <summary>
/// Backplate Type volume parameter.
/// </summary>
[Serializable, DebuggerDisplay(k_DebuggerDisplay)]
public sealed class BackplateTypeParameter : VolumeParameter<BackplateType>
{
/// <summary>
/// Backplate Type volume parameter constructor.
/// </summary>
/// <param name="value">Backplate Type parameter.</param>
/// <param name="overrideState">Initial override state.</param>
public BackplateTypeParameter(BackplateType value, bool overrideState = false)
: base(value, overrideState) { }
}
/// <summary>
/// Sky Intensity volume parameter.
/// </summary>
[Serializable, DebuggerDisplay(k_DebuggerDisplay)]
public sealed class SkyIntensityParameter : VolumeParameter<SkyIntensityMode>
{
/// <summary>
/// Sky Intensity volume parameter constructor.
/// </summary>
/// <param name="value">Sky Intensity parameter.</param>
/// <param name="overrideState">Initial override state.</param>
public SkyIntensityParameter(SkyIntensityMode value, bool overrideState = false)
: base(value, overrideState) { }
}
/// <summary>
/// Base class for custom Sky Settings.
/// </summary>
public abstract class SkySettings : VolumeComponent
{
/// <summary>Rotation of the sky.</summary>
[Tooltip("Sets the rotation of the sky.")]
public ClampedFloatParameter rotation = new ClampedFloatParameter(0.0f, 0.0f, 360.0f);
/// <summary>Intensity mode of the sky.</summary>
[Tooltip("Specifies the intensity mode HDRP uses for the sky.")]
public SkyIntensityParameter skyIntensityMode = new SkyIntensityParameter(SkyIntensityMode.Exposure);
/// <summary>Exposure of the sky.</summary>
[Tooltip("Sets the exposure of the sky in EV.")]
public FloatParameter exposure = new FloatParameter(0.0f);
/// <summary>Intensity Multipler of the sky.</summary>
[Tooltip("Sets the intensity multiplier for the sky.")]
public MinFloatParameter multiplier = new MinFloatParameter(1.0f, 0.0f);
/// <summary>Informative helper that displays the relative intensity (in Lux) for the current HDR texture set in HDRI Sky.</summary>
[Tooltip("Informative helper that displays the relative intensity (in Lux) for the current HDR texture set in HDRI Sky.")]
public MinFloatParameter upperHemisphereLuxValue = new MinFloatParameter(1.0f, 0.0f);
/// <summary>Informative helper that displays Show the color of Shadow.</summary>
[Tooltip("Informative helper that displays Show the color of Shadow.")]
public Vector3Parameter upperHemisphereLuxColor = new Vector3Parameter(new Vector3(0, 0, 0));
/// <summary>Absolute intensity (in lux) of the sky.</summary>
[Tooltip("Sets the absolute intensity (in Lux) of the current HDR texture set in HDRI Sky. Functions as a Lux intensity multiplier for the sky.")]
public FloatParameter desiredLuxValue = new FloatParameter(20000);
/// <summary>Update mode of the sky.</summary>
[Tooltip("Specifies when HDRP updates the environment lighting. When set to OnDemand, use HDRenderPipeline.RequestSkyEnvironmentUpdate() to request an update.")]
public EnvUpdateParameter updateMode = new EnvUpdateParameter(EnvironmentUpdateMode.OnChanged);
/// <summary>In case of real-time update mode, time between updates. 0 means every frame.</summary>
[Tooltip("Sets the period, in seconds, at which HDRP updates the environment ligting (0 means HDRP updates it every frame).")]
public MinFloatParameter updatePeriod = new MinFloatParameter(0.0f, 0.0f);
/// <summary>True if the sun disk should be included in the baking information (where available).</summary>
[Tooltip("When enabled, HDRP uses the Sun Disk in baked lighting.")]
public BoolParameter includeSunInBaking = new BoolParameter(false);
static Dictionary<Type, int> skyUniqueIDs = new Dictionary<Type, int>();
/// <summary>
/// Returns the hash code of the sky parameters.
/// </summary>
/// <param name="camera">The camera we want to use to compute the hash of the sky.</param>
/// <returns>The hash code of the sky parameters.</returns>
virtual public int GetHashCode(Camera camera)
{
// By default we don't need to consider the camera position.
return GetHashCode();
}
/// <summary>
/// Returns the hash code of the sky parameters. When used with PBR Sky please use the GetHashCode variant that takes a camera as parameter.
/// </summary>
/// <returns>The hash code of the sky parameters.</returns>
public override int GetHashCode()
{
unchecked
{
#if UNITY_2019_3 // In 2019.3, when we call GetHashCode on a VolumeParameter it generate garbage (due to the boxing of the generic parameter)
// UpdateMode and period should not be part of the hash as they do not influence rendering itself.
int hash = 13;
hash = hash * 23 + rotation.value.GetHashCode();
hash = hash * 23 + exposure.value.GetHashCode();
hash = hash * 23 + multiplier.value.GetHashCode();
hash = hash * 23 + desiredLuxValue.value.GetHashCode();
hash = hash * 23 + skyIntensityMode.value.GetHashCode();
hash = hash * 23 + includeSunInBaking.value.GetHashCode();
hash = hash * 23 + rotation.overrideState.GetHashCode();
hash = hash * 23 + exposure.overrideState.GetHashCode();
hash = hash * 23 + multiplier.overrideState.GetHashCode();
hash = hash * 23 + desiredLuxValue.overrideState.GetHashCode();
hash = hash * 23 + skyIntensityMode.overrideState.GetHashCode();
hash = hash * 23 + includeSunInBaking.overrideState.GetHashCode();
#else
// UpdateMode and period should not be part of the hash as they do not influence rendering itself.
int hash = 13;
hash = hash * 23 + rotation.GetHashCode();
hash = hash * 23 + exposure.GetHashCode();
hash = hash * 23 + multiplier.GetHashCode();
hash = hash * 23 + desiredLuxValue.GetHashCode();
hash = hash * 23 + skyIntensityMode.GetHashCode();
hash = hash * 23 + includeSunInBaking.GetHashCode();
#endif
return hash;
}
}
/// <summary>
/// Returns the sky type unique ID.
/// Use this to override the skyType in the Visual Environment volume component.
/// </summary>
/// <typeparam name="T">Type of the sky.</typeparam>
/// <returns>The unique ID for the requested sky type.</returns>
public static int GetUniqueID<T>()
{
return GetUniqueID(typeof(T));
}
/// <summary>
/// Returns the sky type unique ID.
/// Use this to override the skyType in the Visual Environment volume component.
/// </summary>
/// <param name="type">Type of the sky.</param>
/// <returns>The unique ID for the requested sky type.</returns>
public static int GetUniqueID(Type type)
{
int uniqueID;
if (!skyUniqueIDs.TryGetValue(type, out uniqueID))
{
var uniqueIDs = type.GetCustomAttributes(typeof(SkyUniqueID), false);
uniqueID = (uniqueIDs.Length == 0) ? -1 : ((SkyUniqueID)uniqueIDs[0]).uniqueID;
skyUniqueIDs[type] = uniqueID;
}
return uniqueID;
}
/// <summary>
/// Returns the sky intensity as determined by this SkySetting.
/// </summary>
/// <returns>The sky intensity.</returns>
public float GetIntensityFromSettings()
{
float skyIntensity = 1.0f;
switch (skyIntensityMode.value)
{
case SkyIntensityMode.Exposure:
// Note: Here we use EV100 of sky as a multiplier, so it is the opposite of when use with a Camera
// because for sky/light, higher EV mean brighter, but for camera higher EV mean darker scene
skyIntensity *= ColorUtils.ConvertEV100ToExposure(-exposure.value);
break;
case SkyIntensityMode.Multiplier:
skyIntensity *= multiplier.value;
break;
case SkyIntensityMode.Lux:
skyIntensity *= desiredLuxValue.value / Mathf.Max(upperHemisphereLuxValue.value, 1e-5f);
break;
}
return skyIntensity;
}
/// <summary>
/// Determines if the SkySettings is significantly divergent from another. This is going to be used to determine whether
/// to reset completely the ambient probe instead of using previous one when waiting for current data upon changes.
/// Override this to have a per-sky specific heuristic.
/// </summary>
/// <param name="otherSettings">The settings to compare with.</param>
/// <returns>Whether the settings are deemed very different.</returns>
public virtual bool SignificantlyDivergesFrom(SkySettings otherSettings)
{
if (otherSettings == null || otherSettings.GetSkyRendererType() != GetSkyRendererType())
return true;
float thisIntensity = GetIntensityFromSettings();
float otherIntensity = otherSettings.GetIntensityFromSettings();
// This is an arbitrary difference threshold. This needs to be re-evaluated in case it is proven problematic
float intensityRatio = thisIntensity > otherIntensity ? (thisIntensity / otherIntensity) : (otherIntensity / thisIntensity);
const float ratioThreshold = 3.0f;
return intensityRatio > ratioThreshold;
}
/// <summary>
/// Returns the class type of the SkyRenderer associated with this Sky Settings.
/// </summary>
/// <returns>The class type of the SkyRenderer associated with this Sky Settings.</returns>
public abstract Type GetSkyRendererType();
// Keeping this API internal for now.
// It's required for PBR sky to interact correctly with baking but we are not 100% set on the interface yet.
internal virtual Vector3 EvaluateAtmosphericAttenuation(Vector3 sunDirection, Vector3 cameraPosition)
{
return Vector3.one;
}
}
}