You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

271 lines
12 KiB

using System;
namespace UnityEngine.Rendering
{
/// <summary>
/// A marker to adjust probes in an area of the scene.
/// </summary>
[CoreRPHelpURL("probevolumes-adjustment-volume-component-reference", "com.unity.render-pipelines.high-definition")]
[ExecuteAlways]
[AddComponentMenu("Rendering/Probe Adjustment Volume")]
public partial class ProbeAdjustmentVolume : MonoBehaviour, ISerializationCallbackReceiver
{
/// <summary>The type of shape that an adjustment volume can take. </summary>
public enum Shape
{
/// <summary>A Box shape.</summary>
Box,
/// <summary>A Sphere shape.</summary>
Sphere,
};
/// <summary>The shape of the adjustment volume</summary>
[Tooltip("Select the shape used for this Probe Adjustment Volume.")]
public Shape shape = Shape.Box;
/// <summary>
/// The size for box shape.
/// </summary>
[Min(0.0f), Tooltip("Modify the size of this Probe Adjustment Volume. This is unaffected by the GameObject's Transform's Scale property.")]
public Vector3 size = new Vector3(1, 1, 1);
/// <summary>
/// The size for sphere shape.
/// </summary>
[Min(0.0f), Tooltip("Modify the radius of this Probe Adjustment Volume. This is unaffected by the GameObject's Transform's Scale property.")]
public float radius = 1.0f;
/// <summary>The mode that adjustment volume will operate in. It determines what probes falling within the volume will do. </summary>
public enum Mode
{
/// <summary>Invalidate the probes within the adjustment volume.</summary>
InvalidateProbes,
/// <summary>Override the dilation validity threshold for the probes within the adjustment volume.</summary>
OverrideValidityThreshold,
/// <summary>Apply an explicit virtual offset to the probes within the adjustment volume.</summary>
ApplyVirtualOffset,
/// <summary>Override the virtual offset settings for the probes within the adjustment volume.</summary>
OverrideVirtualOffsetSettings,
/// <summary>Override the dynamic sky shading direction for the probes within the adjustment volume.</summary>
OverrideSkyDirection,
/// <summary>Override the Lightmapper sample count for the probes within the adjustment volume.</summary>
OverrideSampleCount,
/// <summary>Control the rendering layer masks for the probes within the adjustment volume.</summary>
OverrideRenderingLayerMask,
/// <summary>Scale probe intensity.</summary>
IntensityScale = 99, // make sure this appears last
};
/// <summary>The mode that adjustment volume will operate in. It determines what probes falling within the volume will do. </summary>
public enum RenderingLayerMaskOperation
{
/// <summary>Overrides the rendering layer mask for the probes within the adjustment volume.</summary>
Override,
/// <summary>Add a rendering layer to the probes within the adjustment volume.</summary>
Add,
/// <summary>Removes a rendering layer to the probes within the adjustment volume.</summary>
Remove,
};
/// <summary>Choose what to do with probes falling inside this volume</summary>
public Mode mode = Mode.InvalidateProbes;
/// <summary>
/// A scale to apply to probes falling within the invalidation volume. It is really important to use this with caution as it can lead to inconsistent lighting.
/// </summary>
[Range(0.0001f, 2.0f), Tooltip("A multiplier applied to the intensity of probes covered by this Probe Adjustment Volume.")]
public float intensityScale = 1.0f;
/// <summary>
/// The overridden dilation threshold.
/// </summary>
[Range(0.0f, 0.95f)]
public float overriddenDilationThreshold = 0.75f;
/// <summary>The rotation angles for the virtual offset direction.</summary>
public Vector3 virtualOffsetRotation = Vector3.zero;
/// <summary>Determines how far probes are pushed along the specified virtual offset direction.</summary>
[Min(0.0f)]
public float virtualOffsetDistance = 1.0f;
/// <summary>Determines how far Unity pushes a probe out of geometry after a ray hit.</summary>
[Range(0f, 1f), Tooltip("Determines how far Unity pushes a probe out of geometry after a ray hit.")]
public float geometryBias = 0.01f;
/// <summary>Virtual Offset validity threshold.</summary>
[Range(0f, 0.95f)]
public float virtualOffsetThreshold = 0.75f;
/// <summary>Distance from the probe position used to determine the origin of the sampling ray.</summary>
[Range(-0.05f, 0f), Tooltip("Distance from the probe position used to determine the origin of the sampling ray.")]
public float rayOriginBias = -0.001f;
/// <summary>The sky direction.</summary>
[Tooltip("The direction for sampling the ambient probe in worldspace when using the Sky Visibility feature.")]
public Vector3 skyDirection = Vector3.zero;
internal Vector3 skyShadingDirectionRotation = Vector3.zero;
/// <summary>Number of samples for direct lighting computations.</summary>
[Logarithmic(1, 1024), Tooltip("Number of samples for direct lighting computations.")]
public int directSampleCount = 32;
/// <summary>Number of samples for indirect lighting computations. This includes environment samples.</summary>
[Logarithmic(1, 8192), Tooltip("Number of samples for indirect lighting computations. This includes environment samples.")]
public int indirectSampleCount = 512;
/// <summary>Multiplier for the number of samples specified above.</summary>
[Min(0), Tooltip("Multiplier for the number of samples specified above.")]
public int sampleCountMultiplier = 4;
/// <summary>Maximum number of bounces for indirect lighting.</summary>
[Min(0), Tooltip("Maximum number of bounces for indirect lighting.")]
public int maxBounces = 2;
/// <summary>Controls the number of samples per probe for sky occlusion baking.</summary>
[Logarithmic(1, ProbeVolumeBakingSet.k_MaxSkyOcclusionBakingSamples)]
public int skyOcclusionSampleCount = 2048;
/// <summary>Controls the number of bounces per light path for sky occlusion baking.</summary>
[Range(0, 5)]
public int skyOcclusionMaxBounces = 2;
/// <summary>Rendering Layer Mask operation.</summary>
public RenderingLayerMaskOperation renderingLayerMaskOperation;
/// <summary>Rendering layer mask used for the combine operation with the probes inside the volume.</summary>
public byte renderingLayerMask;
#if UNITY_EDITOR
[SerializeField] internal int cachedHashCode = 0;
public override int GetHashCode()
{
int hash = 17;
unchecked
{
hash = hash * 23 + gameObject.transform.worldToLocalMatrix.GetHashCode();
hash = hash * 23 + shape.GetHashCode();
hash = hash * 23 + size.GetHashCode();
hash = hash * 23 + radius.GetHashCode();
hash = hash * 23 + mode.GetHashCode();
hash = hash * 23 + intensityScale.GetHashCode();
hash = hash * 23 + overriddenDilationThreshold.GetHashCode();
hash = hash * 23 + virtualOffsetRotation.GetHashCode();
hash = hash * 23 + virtualOffsetDistance.GetHashCode();
hash = hash * 23 + geometryBias.GetHashCode();
hash = hash * 23 + rayOriginBias.GetHashCode();
hash = hash * 23 + skyDirection.GetHashCode();
hash = hash * 23 + skyShadingDirectionRotation.GetHashCode();
hash = hash * 23 + directSampleCount.GetHashCode();
hash = hash * 23 + indirectSampleCount.GetHashCode();
hash = hash * 23 + sampleCountMultiplier.GetHashCode();
hash = hash * 23 + maxBounces.GetHashCode();
hash = hash * 23 + skyOcclusionSampleCount.GetHashCode();
hash = hash * 23 + skyOcclusionMaxBounces.GetHashCode();
}
return hash;
}
#endif
#if UNITY_EDITOR
/// <summary>
/// Returns the extents of the volume.
/// </summary>
/// <returns>The extents of the ProbeVolume.</returns>
public Vector3 GetExtents()
{
return size;
}
internal void GetOBBandAABB(out ProbeReferenceVolume.Volume volume, out Bounds bounds)
{
if (shape == Shape.Box)
{
volume = new ProbeReferenceVolume.Volume(Matrix4x4.TRS(transform.position, transform.rotation, GetExtents()), 0, 0);
bounds = volume.CalculateAABB();
}
else
{
volume = default;
bounds = new Bounds(transform.position, radius * Vector3.up);
}
}
internal float ComputeVolume(in ProbeReferenceVolume.Volume touchupOBB)
{
if (shape == Shape.Box)
return touchupOBB.X.magnitude * touchupOBB.Y.magnitude * touchupOBB.Z.magnitude;
else
return (4.0f / 3.0f) * Mathf.PI * radius * radius * radius;
}
internal bool IntersectsVolume(in ProbeReferenceVolume.Volume touchupOBB, in Bounds touchupBounds, Bounds volumeBounds)
{
if (shape == Shape.Box)
return ProbeVolumePositioning.OBBAABBIntersect(touchupOBB, volumeBounds, touchupBounds);
else
return volumeBounds.SqrDistance(touchupBounds.center) < radius * radius;
}
internal bool ContainsPoint(in ProbeReferenceVolume.Volume touchupOBB, in Vector3 touchupCenter, in Vector3 position)
{
if (shape == Shape.Box)
return ProbeVolumePositioning.OBBContains(touchupOBB, position);
else
return (touchupCenter - position).sqrMagnitude < radius * radius;
}
internal Vector3 GetVirtualOffset()
{
if (mode != Mode.ApplyVirtualOffset)
return Vector3.zero;
return (transform.rotation * Quaternion.Euler(virtualOffsetRotation) * Vector3.forward) * virtualOffsetDistance;
}
#endif
// Migration related stuff
enum Version
{
Initial,
Mode,
Count
}
[SerializeField]
Version version = Version.Count;
// This piece of code is needed because some objects could have been created before existence of Version enum
/// <summary>OnBeforeSerialize needed to handle migration before the versioning system was in place.</summary>
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
if (version == Version.Count) // serializing a newly created object
version = Version.Count - 1; // mark as up to date
}
/// <summary>OnAfterDeserialize needed to handle migration before the versioning system was in place.</summary>
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (version == Version.Count) // deserializing and object without version
version = Version.Initial; // reset to run the migration
if (version < Version.Mode)
{
#pragma warning disable 618 // Type or member is obsolete
if (invalidateProbes)
mode = Mode.InvalidateProbes;
else if (overrideDilationThreshold)
mode = Mode.OverrideValidityThreshold;
#pragma warning restore 618
version = Version.Mode;
}
}
}
}