A game about forced loneliness, made by TACStudios
at master 291 lines 13 kB view raw
1using System; 2 3namespace UnityEngine.Rendering 4{ 5 /// <summary> 6 /// A marker to adjust probes in an area of the scene. 7 /// </summary> 8 [CoreRPHelpURL("probevolumes-settings#probe-adjustment-volume", "com.unity.render-pipelines.high-definition")] 9 [ExecuteAlways] 10 [AddComponentMenu("Rendering/Probe Adjustment Volume")] 11 public class ProbeAdjustmentVolume : MonoBehaviour, ISerializationCallbackReceiver 12 { 13 /// <summary>The type of shape that an adjustment volume can take. </summary> 14 public enum Shape 15 { 16 /// <summary>A Box shape.</summary> 17 Box, 18 /// <summary>A Sphere shape.</summary> 19 Sphere, 20 }; 21 22 /// <summary>The shape of the adjustment volume</summary> 23 [Tooltip("Select the shape used for this Probe Adjustment Volume.")] 24 public Shape shape = Shape.Box; 25 26 /// <summary> 27 /// The size for box shape. 28 /// </summary> 29 [Min(0.0f), Tooltip("Modify the size of this Probe Adjustment Volume. This is unaffected by the GameObject's Transform's Scale property.")] 30 public Vector3 size = new Vector3(1, 1, 1); 31 32 /// <summary> 33 /// The size for sphere shape. 34 /// </summary> 35 [Min(0.0f), Tooltip("Modify the radius of this Probe Adjustment Volume. This is unaffected by the GameObject's Transform's Scale property.")] 36 public float radius = 1.0f; 37 38 39 /// <summary>The mode that adjustment volume will operate in. It determines what probes falling within the volume will do. </summary> 40 public enum Mode 41 { 42 /// <summary>Invalidate the probes within the adjustment volume.</summary> 43 InvalidateProbes, 44 /// <summary>Override the dilation validity threshold for the probes within the adjustment volume.</summary> 45 OverrideValidityThreshold, 46 /// <summary>Apply an explicit virtual offset to the probes within the adjustment volume.</summary> 47 ApplyVirtualOffset, 48 /// <summary>Override the virtual offset settings for the probes within the adjustment volume.</summary> 49 OverrideVirtualOffsetSettings, 50 /// <summary>Override the dynamic sky shading direction for the probes within the adjustment volume.</summary> 51 OverrideSkyDirection, 52 /// <summary>Override the Lightmapper sample count for the probes within the adjustment volume.</summary> 53 OverrideSampleCount, 54 /// <summary>Control the rendering layer masks for the probes within the adjustment volume.</summary> 55 OverrideRenderingLayerMask, 56 57 /// <summary>Scale probe intensity.</summary> 58 IntensityScale = 99, // make sure this appears last 59 }; 60 61 /// <summary>The mode that adjustment volume will operate in. It determines what probes falling within the volume will do. </summary> 62 public enum RenderingLayerMaskOperation 63 { 64 /// <summary>Overrides the rendering layer mask for the probes within the adjustment volume.</summary> 65 Override, 66 /// <summary>Add a rendering layer to the probes within the adjustment volume.</summary> 67 Add, 68 /// <summary>Removes a rendering layer to the probes within the adjustment volume.</summary> 69 Remove, 70 }; 71 72 /// <summary>Choose what to do with probes falling inside this volume</summary> 73 public Mode mode = Mode.InvalidateProbes; 74 75 /// <summary> 76 /// 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. 77 /// </summary> 78 [Range(0.0001f, 2.0f), Tooltip("A multiplier applied to the intensity of probes covered by this Probe Adjustment Volume.")] 79 public float intensityScale = 1.0f; 80 81 /// <summary> 82 /// The overridden dilation threshold. 83 /// </summary> 84 [Range(0.0f, 0.95f)] 85 public float overriddenDilationThreshold = 0.75f; 86 87 /// <summary>The rotation angles for the virtual offset direction.</summary> 88 public Vector3 virtualOffsetRotation = Vector3.zero; 89 90 /// <summary>Determines how far probes are pushed along the specified virtual offset direction.</summary> 91 [Min(0.0f)] 92 public float virtualOffsetDistance = 1.0f; 93 94 /// <summary>Determines how far Unity pushes a probe out of geometry after a ray hit.</summary> 95 [Range(0f, 1f), Tooltip("Determines how far Unity pushes a probe out of geometry after a ray hit.")] 96 public float geometryBias = 0.01f; 97 98 /// <summary>Virtual Offset validity threshold.</summary> 99 [Range(0f, 0.95f)] 100 public float virtualOffsetThreshold = 0.75f; 101 102 /// <summary>Distance from the probe position used to determine the origin of the sampling ray.</summary> 103 [Range(-0.05f, 0f), Tooltip("Distance from the probe position used to determine the origin of the sampling ray.")] 104 public float rayOriginBias = -0.001f; 105 106 /// <summary>The sky direction.</summary> 107 [Tooltip("The direction for sampling the ambient probe in worldspace when using the Sky Visibility feature.")] 108 public Vector3 skyDirection = Vector3.zero; 109 110 internal Vector3 skyShadingDirectionRotation = Vector3.zero; 111 112 /// <summary>Number of samples for direct lighting computations.</summary> 113 [Logarithmic(1, 1024), Tooltip("Number of samples for direct lighting computations.")] 114 public int directSampleCount = 32; 115 116 /// <summary>Number of samples for indirect lighting computations. This includes environment samples.</summary> 117 [Logarithmic(1, 8192), Tooltip("Number of samples for indirect lighting computations. This includes environment samples.")] 118 public int indirectSampleCount = 512; 119 120 /// <summary>Multiplier for the number of samples specified above.</summary> 121 [Min(0), Tooltip("Multiplier for the number of samples specified above.")] 122 public int sampleCountMultiplier = 4; 123 124 /// <summary>Maximum number of bounces for indirect lighting.</summary> 125 [Min(0), Tooltip("Maximum number of bounces for indirect lighting.")] 126 public int maxBounces = 2; 127 128 /// <summary>Controls the number of samples per probe for sky occlusion baking.</summary> 129 [Logarithmic(1, ProbeVolumeBakingSet.k_MaxSkyOcclusionBakingSamples)] 130 public int skyOcclusionSampleCount = 2048; 131 132 /// <summary>Controls the number of bounces per light path for sky occlusion baking.</summary> 133 [Range(0, 5)] 134 public int skyOcclusionMaxBounces = 2; 135 136 /// <summary>Rendering Layer Mask operation.</summary> 137 public RenderingLayerMaskOperation renderingLayerMaskOperation; 138 139 /// <summary>Rendering layer mask used for the combine operation with the probes inside the volume.</summary> 140 public byte renderingLayerMask; 141 142#if UNITY_EDITOR 143 [SerializeField] internal int cachedHashCode = 0; 144 145 public override int GetHashCode() 146 { 147 int hash = 17; 148 149 unchecked 150 { 151 hash = hash * 23 + gameObject.transform.worldToLocalMatrix.GetHashCode(); 152 hash = hash * 23 + shape.GetHashCode(); 153 hash = hash * 23 + size.GetHashCode(); 154 hash = hash * 23 + radius.GetHashCode(); 155 hash = hash * 23 + mode.GetHashCode(); 156 hash = hash * 23 + intensityScale.GetHashCode(); 157 hash = hash * 23 + overriddenDilationThreshold.GetHashCode(); 158 hash = hash * 23 + virtualOffsetRotation.GetHashCode(); 159 hash = hash * 23 + virtualOffsetDistance.GetHashCode(); 160 hash = hash * 23 + geometryBias.GetHashCode(); 161 hash = hash * 23 + rayOriginBias.GetHashCode(); 162 hash = hash * 23 + skyDirection.GetHashCode(); 163 hash = hash * 23 + skyShadingDirectionRotation.GetHashCode(); 164 hash = hash * 23 + directSampleCount.GetHashCode(); 165 hash = hash * 23 + indirectSampleCount.GetHashCode(); 166 hash = hash * 23 + sampleCountMultiplier.GetHashCode(); 167 hash = hash * 23 + maxBounces.GetHashCode(); 168 hash = hash * 23 + skyOcclusionSampleCount.GetHashCode(); 169 hash = hash * 23 + skyOcclusionMaxBounces.GetHashCode(); 170 } 171 172 return hash; 173 } 174#endif 175 176#if UNITY_EDITOR 177 /// <summary> 178 /// Returns the extents of the volume. 179 /// </summary> 180 /// <returns>The extents of the ProbeVolume.</returns> 181 public Vector3 GetExtents() 182 { 183 return size; 184 } 185 186 internal void GetOBBandAABB(out ProbeReferenceVolume.Volume volume, out Bounds bounds) 187 { 188 if (shape == Shape.Box) 189 { 190 volume = new ProbeReferenceVolume.Volume(Matrix4x4.TRS(transform.position, transform.rotation, GetExtents()), 0, 0); 191 bounds = volume.CalculateAABB(); 192 } 193 else 194 { 195 volume = default; 196 bounds = new Bounds(transform.position, radius * Vector3.up); 197 } 198 } 199 200 internal float ComputeVolume(in ProbeReferenceVolume.Volume touchupOBB) 201 { 202 if (shape == Shape.Box) 203 return touchupOBB.X.magnitude * touchupOBB.Y.magnitude * touchupOBB.Z.magnitude; 204 else 205 return (4.0f / 3.0f) * Mathf.PI * radius * radius * radius; 206 } 207 208 internal bool IntersectsVolume(in ProbeReferenceVolume.Volume touchupOBB, in Bounds touchupBounds, Bounds volumeBounds) 209 { 210 if (shape == Shape.Box) 211 return ProbeVolumePositioning.OBBAABBIntersect(touchupOBB, volumeBounds, touchupBounds); 212 else 213 return volumeBounds.SqrDistance(touchupBounds.center) < radius * radius; 214 } 215 216 internal bool ContainsPoint(in ProbeReferenceVolume.Volume touchupOBB, in Vector3 touchupCenter, in Vector3 position) 217 { 218 if (shape == Shape.Box) 219 return ProbeVolumePositioning.OBBContains(touchupOBB, position); 220 else 221 return (touchupCenter - position).sqrMagnitude < radius * radius; 222 } 223 224 internal Vector3 GetVirtualOffset() 225 { 226 if (mode != Mode.ApplyVirtualOffset) 227 return Vector3.zero; 228 return (transform.rotation * Quaternion.Euler(virtualOffsetRotation) * Vector3.forward) * virtualOffsetDistance; 229 } 230 231 void OnDrawGizmos() 232 { 233 Gizmos.DrawIcon(transform.position, ProbeVolume.s_gizmosLocationPath + "ProbeTouchupVolume.png", true); 234 } 235#endif 236 237 238 // Migration related stuff 239 240 enum Version 241 { 242 Initial, 243 Mode, 244 245 Count 246 } 247 248 [SerializeField] 249 Version version = Version.Count; 250 251 /// <summary>Whether to invalidate all probes falling within this volume.</summary> 252 [Obsolete("Use mode")] 253 public bool invalidateProbes = false; 254 /// <summary>Whether to use a custom threshold for dilation for probes falling withing this volume.</summary> 255 [Obsolete("Use mode")] 256 public bool overrideDilationThreshold = false; 257 258 void Awake() 259 { 260 if (version == Version.Count) 261 return; 262 263 if (version == Version.Initial) 264 { 265#pragma warning disable 618 // Type or member is obsolete 266 if (invalidateProbes) 267 mode = Mode.InvalidateProbes; 268 else if (overrideDilationThreshold) 269 mode = Mode.OverrideValidityThreshold; 270#pragma warning restore 618 271 272 version++; 273 } 274 } 275 276 // This piece of code is needed because some objects could have been created before existence of Version enum 277 /// <summary>OnBeforeSerialize needed to handle migration before the versioning system was in place.</summary> 278 void ISerializationCallbackReceiver.OnBeforeSerialize() 279 { 280 if (version == Version.Count) // serializing a newly created object 281 version = Version.Count - 1; // mark as up to date 282 } 283 284 /// <summary>OnAfterDeserialize needed to handle migration before the versioning system was in place.</summary> 285 void ISerializationCallbackReceiver.OnAfterDeserialize() 286 { 287 if (version == Version.Count) // deserializing and object without version 288 version = Version.Initial; // reset to run the migration 289 } 290 } 291}