#if UNITY_EDITOR
using UnityEditor;
#endif
using System;
namespace UnityEngine.Rendering
{
///
/// Data-Driven Lens Flare can be added on any gameobject
///
[ExecuteAlways]
[AddComponentMenu("Rendering/Lens Flare (SRP)")]
public sealed class LensFlareComponentSRP : MonoBehaviour
{
[SerializeField]
private LensFlareDataSRP m_LensFlareData = null;
///
/// Lens flare asset used on this component
///
public LensFlareDataSRP lensFlareData
{
get
{
return m_LensFlareData;
}
set
{
m_LensFlareData = value;
OnValidate();
}
}
///
/// Intensity
///
[Min(0.0f)]
public float intensity = 1.0f;
///
/// Distance used to scale the Distance Attenuation Curve
///
[Min(1e-5f)]
public float maxAttenuationDistance = 100.0f;
///
/// Distance used to scale the Scale Attenuation Curve
///
[Min(1e-5f)]
public float maxAttenuationScale = 100.0f;
///
/// Attenuation by distance
///
public AnimationCurve distanceAttenuationCurve = new AnimationCurve(new Keyframe(0.0f, 1.0f), new Keyframe(1.0f, 0.0f));
///
/// Scale by distance, use the same distance as distanceAttenuationCurve
///
public AnimationCurve scaleByDistanceCurve = new AnimationCurve(new Keyframe(0.0f, 1.0f), new Keyframe(1.0f, 0.0f));
///
/// If component attached to a light, attenuation the lens flare per light type
///
public bool attenuationByLightShape = true;
///
/// Attenuation used radially, which allow for instance to enable flare only on the edge of the screen
///
public AnimationCurve radialScreenAttenuationCurve = new AnimationCurve(new Keyframe(0.0f, 1.0f), new Keyframe(1.0f, 1.0f));
///
/// Enable Occlusion feature
///
public bool useOcclusion = false;
///
/// Radius around the light used to occlude the flare (value in world space)
///
[Min(0.0f)]
public float occlusionRadius = 0.1f;
///
/// Enable Occlusion using Background Cloud (for instance: CloudLayer)
///
public bool useBackgroundCloudOcclusion = false;
///
/// Random Samples Count used inside the disk with 'occlusionRadius'
///
[Range(1, 64)]
public uint sampleCount = 32;
///
/// Z Occlusion Offset allow us to offset the plane where the disc of occlusion is place (closer to camera), value on world space.
/// Useful for instance to sample occlusion outside a light bulb if we place a flare inside the light bulb
///
public float occlusionOffset = 0.05f;
///
/// Global Scale
///
[Min(0.0f)]
public float scale = 1.0f;
///
/// If allowOffScreen is true then If the lens flare is outside the screen we still emit the flare on screen
///
public bool allowOffScreen = false;
///
/// If volumetricCloudOcclusion is true then use the volumetric cloud (on HDRP only) for the occlusion
///
public bool volumetricCloudOcclusion = false;
/// Our default celestial body will have an angular radius of 3.3 degrees. This is an arbitrary number, but must be kept constant
/// so the occlusion radius for direct lights is consistent regardless of near / far clip plane configuration.
private static float sCelestialAngularRadius = 3.3f * Mathf.PI / 180.0f;
///
/// OcclusionRemapCurve allow the occlusion [from 0 to 1] to be remap with any desired shape.
///
public TextureCurve occlusionRemapCurve = new TextureCurve(AnimationCurve.Linear(0.0f, 0.0f, 1.0f, 1.0f), 1.0f, false, new Vector2(0.0f, 1.0f));
///
/// Retrieves the projected occlusion radius from a particular celestial in the infinity plane with an angular radius.
/// This is used for directional lights which require to have consistent occlusion radius regardless of the near/farplane configuration.
///
/// The camera utilized to calculate the occlusion radius
/// The value, in world units, of the occlusion angular radius.
public float celestialProjectedOcclusionRadius(Camera mainCam)
{
float projectedRadius = (float)Math.Tan(sCelestialAngularRadius) * mainCam.farClipPlane;
return occlusionRadius * projectedRadius;
}
///
/// Add or remove the lens flare to the queue of PostProcess
///
void OnEnable()
{
if (lensFlareData)
LensFlareCommonSRP.Instance.AddData(this);
else
LensFlareCommonSRP.Instance.RemoveData(this);
}
///
/// Remove the lens flare from the queue of PostProcess
///
void OnDisable()
{
LensFlareCommonSRP.Instance.RemoveData(this);
}
///
/// Add or remove the lens flare from the queue of PostProcess
///
void OnValidate()
{
if (isActiveAndEnabled && lensFlareData != null)
{
LensFlareCommonSRP.Instance.AddData(this);
}
else
{
LensFlareCommonSRP.Instance.RemoveData(this);
}
}
#if UNITY_EDITOR
private float sDebugClippingSafePercentage = 0.9f; //for debug gizmo, only push 90% further so we avoid clipping of debug lines.
void OnDrawGizmosSelected()
{
Camera mainCam = Camera.current;
if (mainCam != null && useOcclusion)
{
Vector3 positionWS;
float adjustedOcclusionRadius = occlusionRadius;
Light light = GetComponent();
if (light != null && light.type == LightType.Directional)
{
positionWS = -transform.forward * (mainCam.farClipPlane * sDebugClippingSafePercentage) + mainCam.transform.position;
adjustedOcclusionRadius = celestialProjectedOcclusionRadius(mainCam);
}
else
{
positionWS = transform.position;
}
Color previousH = Handles.color;
Color previousG = Gizmos.color;
Handles.color = Color.red;
Gizmos.color = Color.red;
Vector3 dir = (mainCam.transform.position - positionWS).normalized;
Handles.DrawWireDisc(positionWS + dir * occlusionOffset, dir, adjustedOcclusionRadius, 1.0f);
Gizmos.DrawWireSphere(positionWS, occlusionOffset);
Gizmos.color = previousG;
Handles.color = previousH;
}
}
#endif
}
}