A game about forced loneliness, made by TACStudios
at master 2144 lines 111 kB view raw
1using System; 2using System.Collections.Generic; 3using System.Xml.Linq; 4using UnityEngine.Experimental.Rendering; 5 6namespace UnityEngine.Rendering 7{ 8 /// <summary> 9 /// Common code for all Data-Driven Lens Flare used 10 /// </summary> 11 public sealed class LensFlareCommonSRP 12 { 13 private static LensFlareCommonSRP m_Instance = null; 14 private static readonly object m_Padlock = new object(); 15 /// <summary> 16 /// Class describing internal information stored to describe a shown LensFlare 17 /// </summary> 18 internal class LensFlareCompInfo 19 { 20 /// <summary> 21 /// Index used to compute Occlusion in a fixed order 22 /// </summary> 23 internal int index; 24 25 /// <summary> 26 /// Component used 27 /// </summary> 28 internal LensFlareComponentSRP comp; 29 30 internal LensFlareCompInfo(int idx, LensFlareComponentSRP cmp) 31 { 32 index = idx; 33 comp = cmp; 34 } 35 } 36 37 private static List<LensFlareCompInfo> m_Data = new List<LensFlareCompInfo>(); 38 private static List<int> m_AvailableIndicies = new List<int>(); 39 40 /// <summary> 41 /// Max lens-flares-with-occlusion supported 42 /// </summary> 43 public static int maxLensFlareWithOcclusion = 128; 44 45 46 /// <summary> 47 /// With TAA Occlusion jitter depth, thought frame on HDRP. 48 /// So we do a "unanimity vote" for occlusion thought 'maxLensFlareWithOcclusionTemporalSample' frame 49 /// Important to keep this value maximum of 8 50 /// If this value change that could implies an implementation modification on: 51 /// com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/LensFlareMergeOcclusionDataDriven.compute 52 /// </summary> 53 public static int maxLensFlareWithOcclusionTemporalSample = 8; 54 55 /// <summary> 56 /// Set to 1 to enable temporal sample merge. 57 /// Set to 0 to disable temporal sample merge (must support 16 bit textures, and the occlusion merge must be written in the last texel (vertical) of the lens flare texture. 58 /// </summary> 59 public static int mergeNeeded = 1; 60 61 /// <summary> 62 /// occlusion texture either provided or created automatically by the SRP for lens flare. 63 /// Texture width is the max number of lens flares that have occlusion (x axis the lens flare index). 64 /// y axis is the number of samples (maxLensFlareWithOcclusionTemporalSample) plus the number of merge results. 65 /// Merge results must be done by the SRP and stored in the [(lens flareIndex), (maxLensFlareWithOcclusionTemporalSample + 1)] coordinate. 66 /// Note: It's not supported on OpenGL3 and OpenGLCore 67 /// </summary> 68 public static RTHandle occlusionRT = null; 69 70 private static int frameIdx = 0; 71 72 internal static readonly int _FlareOcclusionPermutation = Shader.PropertyToID("_FlareOcclusionPermutation"); 73 internal static readonly int _FlareOcclusionRemapTex = Shader.PropertyToID("_FlareOcclusionRemapTex"); 74 internal static readonly int _FlareOcclusionTex = Shader.PropertyToID("_FlareOcclusionTex"); 75 internal static readonly int _FlareOcclusionIndex = Shader.PropertyToID("_FlareOcclusionIndex"); 76 internal static readonly int _FlareCloudOpacity = Shader.PropertyToID("_FlareCloudOpacity"); 77 internal static readonly int _FlareSunOcclusionTex = Shader.PropertyToID("_FlareSunOcclusionTex"); 78 internal static readonly int _FlareTex = Shader.PropertyToID("_FlareTex"); 79 internal static readonly int _FlareColorValue = Shader.PropertyToID("_FlareColorValue"); 80 internal static readonly int _FlareData0 = Shader.PropertyToID("_FlareData0"); 81 internal static readonly int _FlareData1 = Shader.PropertyToID("_FlareData1"); 82 internal static readonly int _FlareData2 = Shader.PropertyToID("_FlareData2"); 83 internal static readonly int _FlareData3 = Shader.PropertyToID("_FlareData3"); 84 internal static readonly int _FlareData4 = Shader.PropertyToID("_FlareData4"); 85 internal static readonly int _FlareData5 = Shader.PropertyToID("_FlareData5"); 86 internal static readonly int _FlareRadialTint = Shader.PropertyToID("_FlareRadialTint"); 87 88 internal static readonly int _ViewId = Shader.PropertyToID("_ViewId"); 89 90 internal static readonly int _LensFlareScreenSpaceBloomMipTexture = Shader.PropertyToID("_LensFlareScreenSpaceBloomMipTexture"); 91 internal static readonly int _LensFlareScreenSpaceResultTexture = Shader.PropertyToID("_LensFlareScreenSpaceResultTexture"); 92 internal static readonly int _LensFlareScreenSpaceSpectralLut = Shader.PropertyToID("_LensFlareScreenSpaceSpectralLut"); 93 internal static readonly int _LensFlareScreenSpaceStreakTex = Shader.PropertyToID("_LensFlareScreenSpaceStreakTex"); 94 internal static readonly int _LensFlareScreenSpaceMipLevel = Shader.PropertyToID("_LensFlareScreenSpaceMipLevel"); 95 internal static readonly int _LensFlareScreenSpaceTintColor = Shader.PropertyToID("_LensFlareScreenSpaceTintColor"); 96 internal static readonly int _LensFlareScreenSpaceParams1 = Shader.PropertyToID("_LensFlareScreenSpaceParams1"); 97 internal static readonly int _LensFlareScreenSpaceParams2 = Shader.PropertyToID("_LensFlareScreenSpaceParams2"); 98 internal static readonly int _LensFlareScreenSpaceParams3 = Shader.PropertyToID("_LensFlareScreenSpaceParams3"); 99 internal static readonly int _LensFlareScreenSpaceParams4 = Shader.PropertyToID("_LensFlareScreenSpaceParams4"); 100 internal static readonly int _LensFlareScreenSpaceParams5 = Shader.PropertyToID("_LensFlareScreenSpaceParams5"); 101 102 private LensFlareCommonSRP() 103 { 104 } 105 106 private static readonly bool s_SupportsLensFlare16bitsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R16_SFloat, GraphicsFormatUsage.Render); 107 private static readonly bool s_SupportsLensFlare32bitsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R32_SFloat, GraphicsFormatUsage.Render); 108 109 /// <summary> 110 /// Check if we can use an OcclusionRT 111 /// </summary> 112 /// <returns>return true if we can have the OcclusionRT</returns> 113 static public bool IsOcclusionRTCompatible() 114 { 115#if UNITY_SERVER 116 return false; 117#else 118 return SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES3 && 119 SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLCore && 120 SystemInfo.graphicsDeviceType != GraphicsDeviceType.Null && 121 SystemInfo.graphicsDeviceType != GraphicsDeviceType.WebGPU && 122 (s_SupportsLensFlare16bitsFormat || s_SupportsLensFlare32bitsFormat); //Caching this, because SupportsRenderTextureFormat allocates memory. Go figure. 123#endif 124 } 125 126 static GraphicsFormat GetOcclusionRTFormat() 127 { 128 // SystemInfo.graphicsDeviceType == {GraphicsDeviceType.Direct3D12, GraphicsDeviceType.GameCoreXboxSeries, GraphicsDeviceType.XboxOneD3D12, GraphicsDeviceType.PlayStation5, ...} 129 if (s_SupportsLensFlare16bitsFormat) 130 return GraphicsFormat.R16_SFloat; 131 else 132 // Needed a R32_SFloat for Metal or/and DirectX < 11.3 133 return GraphicsFormat.R32_SFloat; 134 } 135 136 /// <summary> 137 /// Initialization function which must be called by the SRP. 138 /// </summary> 139 static public void Initialize() 140 { 141 frameIdx = 0; 142 if (IsOcclusionRTCompatible()) 143 { 144 // The height of occlusion texture is: 145 // - '1': when no temporal accumulation 146 // - 'maxLensFlareWithOcclusionTemporalSample + 1': for temporal accumulation, useful when TAA enabled 147 if (occlusionRT == null) 148 { 149 occlusionRT = RTHandles.Alloc( 150 width: maxLensFlareWithOcclusion, 151 height: Mathf.Max(mergeNeeded * (maxLensFlareWithOcclusionTemporalSample + 1), 1), 152 format: GetOcclusionRTFormat(), 153 slices: TextureXR.slices, 154 enableRandomWrite: true, 155 dimension: TextureDimension.Tex2DArray); 156 } 157 } 158 } 159 160 /// <summary> 161 /// Disposal function, must be called by the SRP to release all internal textures. 162 /// </summary> 163 static public void Dispose() 164 { 165 if (IsOcclusionRTCompatible()) 166 { 167 if (occlusionRT != null) 168 { 169 RTHandles.Release(occlusionRT); 170 occlusionRT = null; 171 } 172 } 173 } 174 175 /// <summary> 176 /// Current unique instance 177 /// </summary> 178 public static LensFlareCommonSRP Instance 179 { 180 get 181 { 182 if (m_Instance == null) 183 { 184 lock (m_Padlock) 185 { 186 if (m_Instance == null) 187 { 188 m_Instance = new LensFlareCommonSRP(); 189 } 190 } 191 } 192 return m_Instance; 193 } 194 } 195 196 private System.Collections.Generic.List<LensFlareCompInfo> Data { get { return LensFlareCommonSRP.m_Data; } } 197 198 /// <summary> 199 /// Check if we have at least one Lens Flare added on the pool 200 /// </summary> 201 /// <returns>true if no Lens Flare were added</returns> 202 public bool IsEmpty() 203 { 204 return Data.Count == 0; 205 } 206 207 int GetNextAvailableIndex() 208 { 209 if (m_AvailableIndicies.Count == 0) 210 return m_Data.Count; 211 else 212 { 213 int nextIndex = m_AvailableIndicies[m_AvailableIndicies.Count - 1]; 214 m_AvailableIndicies.RemoveAt(m_AvailableIndicies.Count - 1); 215 return nextIndex; 216 } 217 } 218 219 /// <summary> 220 /// Add a new lens flare component on the pool. 221 /// </summary> 222 /// <param name="newData">The new data added</param> 223 public void AddData(LensFlareComponentSRP newData) 224 { 225 Debug.Assert(Instance == this, "LensFlareCommonSRP can have only one instance"); 226 227 if (!m_Data.Exists(x => x.comp == newData)) 228 { 229 m_Data.Add(new LensFlareCompInfo(GetNextAvailableIndex(), newData)); 230 } 231 } 232 233 /// <summary> 234 /// Remove a lens flare data which exist in the pool. 235 /// </summary> 236 /// <param name="data">The data which exist in the pool</param> 237 public void RemoveData(LensFlareComponentSRP data) 238 { 239 Debug.Assert(Instance == this, "LensFlareCommonSRP can have only one instance"); 240 241 LensFlareCompInfo info = m_Data.Find(x => x.comp == data); 242 if (info != null) 243 { 244 int newIndex = info.index; 245 m_Data.Remove(info); 246 m_AvailableIndicies.Add(newIndex); 247 if (m_Data.Count == 0) 248 m_AvailableIndicies.Clear(); 249 } 250 } 251 252 253 /// <summary> 254 /// Attenuation by Light Shape for Point Light 255 /// </summary> 256 /// <returns>Attenuation Factor</returns> 257 static public float ShapeAttenuationPointLight() 258 { 259 return 1.0f; 260 } 261 262 /// <summary> 263 /// Attenuation by Light Shape for Directional Light 264 /// </summary> 265 /// <param name="forward">Forward Vector of Directional Light</param> 266 /// <param name="wo">Vector pointing to the eye</param> 267 /// <returns>Attenuation Factor</returns> 268 static public float ShapeAttenuationDirLight(Vector3 forward, Vector3 wo) 269 { 270 return Mathf.Max(Vector3.Dot(-forward, wo), 0.0f); 271 } 272 273 /// <summary> 274 /// Attenuation by Light Shape for Spot Light with Cone Shape 275 /// </summary> 276 /// <param name="forward">Forward Vector of Directional Light</param> 277 /// <param name="wo">Vector pointing to the eye</param> 278 /// <param name="spotAngle">The angle of the light's spotlight cone in degrees.</param> 279 /// <param name="innerSpotPercent01">Get the inner spot radius between 0 and 1.</param> 280 /// <returns>Attenuation Factor</returns> 281 static public float ShapeAttenuationSpotConeLight(Vector3 forward, Vector3 wo, float spotAngle, float innerSpotPercent01) 282 { 283 float outerDot = Mathf.Max(Mathf.Cos(0.5f * spotAngle * Mathf.Deg2Rad), 0.0f); 284 float innerDot = Mathf.Max(Mathf.Cos(0.5f * spotAngle * Mathf.Deg2Rad * innerSpotPercent01), 0.0f); 285 float dot = Mathf.Max(Vector3.Dot(forward, wo), 0.0f); 286 return Mathf.Clamp01((dot - outerDot) / (innerDot - outerDot)); 287 } 288 289 /// <summary> 290 /// Attenuation by Light Shape for Spot Light with Box Shape 291 /// </summary> 292 /// <param name="forward">Forward Vector of Directional Light</param> 293 /// <param name="wo">Vector pointing to the eye</param> 294 /// <returns>Attenuation Factor</returns> 295 static public float ShapeAttenuationSpotBoxLight(Vector3 forward, Vector3 wo) 296 { 297 return Mathf.Max(Mathf.Sign(Vector3.Dot(forward, wo)), 0.0f); 298 } 299 300 /// <summary> 301 /// Attenuation by Light Shape for Spot Light with Pyramid Shape 302 /// </summary> 303 /// <param name="forward">Forward Vector of Directional Light</param> 304 /// <param name="wo">Vector pointing to the eye</param> 305 /// <returns>Attenuation Factor</returns> 306 static public float ShapeAttenuationSpotPyramidLight(Vector3 forward, Vector3 wo) 307 { 308 return ShapeAttenuationSpotBoxLight(forward, wo); 309 } 310 311 /// <summary> 312 /// Attenuation by Light Shape for Area Light with Tube Shape 313 /// </summary> 314 /// <param name="lightPositionWS">World Space position of the Light</param> 315 /// <param name="lightSide">Vector pointing to the side (right or left) or the light</param> 316 /// <param name="lightWidth">Width (half extent) of the tube light</param> 317 /// <param name="cam">Camera rendering the Tube Light</param> 318 /// <returns>Attenuation Factor</returns> 319 static public float ShapeAttenuationAreaTubeLight(Vector3 lightPositionWS, Vector3 lightSide, float lightWidth, Camera cam) 320 { 321 // Ref: https://hal.archives-ouvertes.fr/hal-02155101/document 322 // Listing 1.6. Analytic line-diffuse integration. 323 float Fpo(float d, float l) 324 { 325 return l / (d * (d * d + l * l)) + Mathf.Atan(l / d) / (d * d); 326 } 327 328 float Fwt(float d, float l) 329 { 330 return l * l / (d * (d * d + l * l)); 331 } 332 333 Vector3 p1Global = lightPositionWS + lightSide * lightWidth * 0.5f; 334 Vector3 p2Global = lightPositionWS - lightSide * lightWidth * 0.5f; 335 Vector3 p1Front = lightPositionWS + cam.transform.right * lightWidth * 0.5f; 336 Vector3 p2Front = lightPositionWS - cam.transform.right * lightWidth * 0.5f; 337 338 Vector3 p1World = cam.transform.InverseTransformPoint(p1Global); 339 Vector3 p2World = cam.transform.InverseTransformPoint(p2Global); 340 Vector3 p1WorldFront = cam.transform.InverseTransformPoint(p1Front); 341 Vector3 p2WorldFront = cam.transform.InverseTransformPoint(p2Front); 342 343 float DiffLineIntegral(Vector3 p1, Vector3 p2) 344 { 345 float diffIntegral; 346 // tangent 347 Vector3 wt = (p2 - p1).normalized; 348 // clamping 349 if (p1.z <= 0.0 && p2.z <= 0.0) 350 { 351 diffIntegral = 0.0f; 352 } 353 else 354 { 355 if (p1.z < 0.0) 356 p1 = (p1 * p2.z - p2 * p1.z) / (+p2.z - p1.z); 357 if (p2.z < 0.0) 358 p2 = (-p1 * p2.z + p2 * p1.z) / (-p2.z + p1.z); 359 // parameterization 360 float l1 = Vector3.Dot(p1, wt); 361 float l2 = Vector3.Dot(p2, wt); 362 // shading point orthonormal projection on the line 363 Vector3 po = p1 - l1 * wt; 364 // distance to line 365 float d = po.magnitude; 366 // integral 367 float integral = (Fpo(d, l2) - Fpo(d, l1)) * po.z + (Fwt(d, l2) - Fwt(d, l1)) * wt.z; 368 diffIntegral = integral / Mathf.PI; 369 } 370 371 return diffIntegral; 372 } 373 374 float frontModulation = DiffLineIntegral(p1WorldFront, p2WorldFront); 375 float worldModulation = DiffLineIntegral(p1World, p2World); 376 377 return frontModulation > 0.0f ? worldModulation / frontModulation : 1.0f; 378 } 379 380 static float ShapeAttenuateForwardLight(Vector3 forward, Vector3 wo) 381 { 382 return Mathf.Max(Vector3.Dot(forward, wo), 0.0f); 383 } 384 385 /// <summary> 386 /// Attenuation by Light Shape for Area Light with Rectangular Shape 387 /// </summary> 388 /// <param name="forward">Forward Vector of Directional Light</param> 389 /// <param name="wo">Vector pointing to the eye</param> 390 /// <returns>Attenuation Factor</returns> 391 static public float ShapeAttenuationAreaRectangleLight(Vector3 forward, Vector3 wo) 392 { 393 return ShapeAttenuateForwardLight(forward, wo); 394 } 395 396 /// <summary> 397 /// Attenuation by Light Shape for Area Light with Disc Shape 398 /// </summary> 399 /// <param name="forward">Forward Vector of Directional Light</param> 400 /// <param name="wo">Vector pointing to the eye</param> 401 /// <returns>Attenuation Factor</returns> 402 static public float ShapeAttenuationAreaDiscLight(Vector3 forward, Vector3 wo) 403 { 404 return ShapeAttenuateForwardLight(forward, wo); 405 } 406 407 static bool IsLensFlareSRPHidden(Camera cam, LensFlareComponentSRP comp, LensFlareDataSRP data) 408 { 409 if (!comp.enabled || 410 !comp.gameObject.activeSelf || 411 !comp.gameObject.activeInHierarchy || 412 data == null || 413 data.elements == null || 414 data.elements.Length == 0 || 415 comp.intensity <= 0.0f || 416 ((cam.cullingMask & (1 << comp.gameObject.layer)) == 0)) 417 return true; 418 419 return false; 420 } 421 422 /// <summary> 423 /// Compute internal parameters needed to render single flare 424 /// </summary> 425 /// <param name="screenPos">The screen position of the flare.</param> 426 /// <param name="translationScale">The scale of translation applied to the flare.</param> 427 /// <param name="rayOff0">The base offset for the flare ray.</param> 428 /// <param name="vLocalScreenRatio">The ratio of the flare's local screen size.</param> 429 /// <param name="angleDeg">The base angle of rotation for the flare.</param> 430 /// <param name="position">The position along the flare's radial line, relative to the source, where 1.0 represents the edge of the screen.</param> 431 /// <param name="angularOffset">Angular offset applied to the flare's position.</param> 432 /// <param name="positionOffset">The offset from the flare's calculated position.</param> 433 /// <param name="autoRotate">Flag to enable automatic rotation based on flare's position.</param> 434 /// <returns>A Vector4 object representing the shader parameters _FlareData0.</returns> 435 static public Vector4 GetFlareData0(Vector2 screenPos, Vector2 translationScale, Vector2 rayOff0, Vector2 vLocalScreenRatio, float angleDeg, float position, float angularOffset, Vector2 positionOffset, bool autoRotate) 436 { 437 if (!SystemInfo.graphicsUVStartsAtTop) 438 { 439 angleDeg *= -1; 440 positionOffset.y *= -1; 441 } 442 443 float globalCos0 = Mathf.Cos(-angularOffset * Mathf.Deg2Rad); 444 float globalSin0 = Mathf.Sin(-angularOffset * Mathf.Deg2Rad); 445 446 Vector2 rayOff = -translationScale * (screenPos + screenPos * (position - 1.0f)); 447 rayOff = new Vector2(globalCos0 * rayOff.x - globalSin0 * rayOff.y, 448 globalSin0 * rayOff.x + globalCos0 * rayOff.y); 449 450 float rotation = angleDeg; 451 452 rotation += 180.0f; 453 if (autoRotate) 454 { 455 Vector2 pos = (rayOff.normalized * vLocalScreenRatio) * translationScale; 456 457 rotation += -Mathf.Rad2Deg * Mathf.Atan2(pos.y, pos.x); 458 } 459 rotation *= Mathf.Deg2Rad; 460 float localCos0 = Mathf.Cos(-rotation); 461 float localSin0 = Mathf.Sin(-rotation); 462 463 return new Vector4(localCos0, localSin0, positionOffset.x + rayOff0.x * translationScale.x, -positionOffset.y + rayOff0.y * translationScale.y); 464 } 465 466 static Vector2 GetLensFlareRayOffset(Vector2 screenPos, float position, float globalCos0, float globalSin0, Vector2 vAspectRatio) 467 { 468 Vector2 rayOff = -(screenPos + screenPos * (position - 1.0f)); 469 return new Vector2(globalCos0 * rayOff.x - globalSin0 * rayOff.y, 470 globalSin0 * rayOff.x + globalCos0 * rayOff.y); 471 } 472 473 static Vector3 WorldToViewport(Camera camera, bool isLocalLight, bool isCameraRelative, Matrix4x4 viewProjMatrix, Vector3 positionWS) 474 { 475 if (isLocalLight) 476 { 477 return WorldToViewportLocal(isCameraRelative, viewProjMatrix, camera.transform.position, positionWS); 478 } 479 else 480 { 481 return WorldToViewportDistance(camera, positionWS); 482 } 483 } 484 485 static Vector3 WorldToViewportLocal(bool isCameraRelative, Matrix4x4 viewProjMatrix, Vector3 cameraPosWS, Vector3 positionWS) 486 { 487 Vector3 localPositionWS = positionWS; 488 if (isCameraRelative) 489 { 490 localPositionWS -= cameraPosWS; 491 } 492 Vector4 viewportPos4 = viewProjMatrix * localPositionWS; 493 Vector3 viewportPos = new Vector3(viewportPos4.x, viewportPos4.y, 0f); 494 viewportPos /= viewportPos4.w; 495 viewportPos.x = viewportPos.x * 0.5f + 0.5f; 496 viewportPos.y = viewportPos.y * 0.5f + 0.5f; 497 viewportPos.y = 1.0f - viewportPos.y; 498 viewportPos.z = viewportPos4.w; 499 return viewportPos; 500 } 501 502 static Vector3 WorldToViewportDistance(Camera cam, Vector3 positionWS) 503 { 504 Vector4 camPos = cam.worldToCameraMatrix * positionWS; 505 Vector4 viewportPos4 = cam.projectionMatrix * camPos; 506 Vector3 viewportPos = new Vector3(viewportPos4.x, viewportPos4.y, 0f); 507 viewportPos /= viewportPos4.w; 508 viewportPos.x = viewportPos.x * 0.5f + 0.5f; 509 viewportPos.y = viewportPos.y * 0.5f + 0.5f; 510 viewportPos.z = viewportPos4.w; 511 return viewportPos; 512 } 513 514 /// <summary> 515 /// Check if at least one LensFlareComponentSRP request occlusion from background clouds 516 /// </summary> 517 /// <param name="cam">Camera</param> 518 /// <returns>true if cloud occlusion is requested</returns> 519 static public bool IsCloudLayerOpacityNeeded(Camera cam) 520 { 521 if (Instance.IsEmpty()) 522 return false; 523 524#if UNITY_EDITOR 525 if (cam.cameraType == CameraType.SceneView) 526 { 527 // Determine whether the "Animated Materials" checkbox is checked for the current view. 528 for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++) // Using a foreach on an ArrayList generates garbage ... 529 { 530 var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView; 531 if (sv.camera == cam && !sv.sceneViewState.flaresEnabled) 532 { 533 return false; 534 } 535 } 536 } 537#endif 538 539 foreach (LensFlareCompInfo info in Instance.Data) 540 { 541 if (info == null || info.comp == null) 542 continue; 543 544 LensFlareComponentSRP comp = info.comp; 545 LensFlareDataSRP data = comp.lensFlareData; 546 547 if (IsLensFlareSRPHidden(cam, comp, data) || 548 !comp.useOcclusion || 549 (comp.useOcclusion && comp.sampleCount == 0)) 550 continue; 551 552 if (comp.environmentOcclusion) 553 return true; 554 } 555 556 return false; 557 } 558 559 static void SetOcclusionPermutation(CommandBuffer cmd, bool useFogOpacityOcclusion, int _FlareSunOcclusionTex, Texture sunOcclusionTexture) 560 { 561 uint occlusionPermutation = (uint)(LensFlareOcclusionPermutation.Depth); 562 563 if (useFogOpacityOcclusion && sunOcclusionTexture != null) 564 { 565 occlusionPermutation |= (uint)(LensFlareOcclusionPermutation.FogOpacity); 566 cmd.SetGlobalTexture(_FlareSunOcclusionTex, sunOcclusionTexture); 567 } 568 569 int convInt = unchecked((int)occlusionPermutation); 570 cmd.SetGlobalInt(_FlareOcclusionPermutation, convInt); 571 } 572 573#if UNITY_EDITOR 574 static bool IsPrefabStageEnabled() 575 { 576 return UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() != null; 577 } 578 579 static LensFlareComponentSRP[] GetLensFlareComponents(GameObject go) 580 { 581 return go.GetComponentsInChildren<LensFlareComponentSRP>(false); 582 } 583 584 static bool IsCurrentPrefabLensFlareComponent(GameObject go, LensFlareComponentSRP[] components, LensFlareComponentSRP comp) 585 { 586 foreach (LensFlareComponentSRP x in components) 587 { 588 if (x == comp) 589 return true; 590 } 591 592 return false; 593 } 594#endif 595 596 /// <summary> 597 /// Effective Job of drawing the set of Lens Flare registered 598 /// </summary> 599 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 600 /// <param name="cam">Camera</param> 601 /// <param name="xr">XR Infos</param> 602 /// <param name="xrIndex">Index of the SinglePass XR</param> 603 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 604 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 605 /// <param name="usePanini">Set if use Panani Projection</param> 606 /// <param name="paniniDistance">Distance used for Panini projection</param> 607 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 608 /// <param name="isCameraRelative">Set if camera is relative</param> 609 /// <param name="cameraPositionWS">Camera World Space position</param> 610 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 611 /// <param name="cmd">Command Buffer</param> 612 /// <param name="taaEnabled">Set if TAA is enabled</param> 613 /// <param name="hasCloudLayer">Unused</param> 614 /// <param name="cloudOpacityTexture">Unused</param> 615 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 616 /// <param name="_FlareOcclusionTex">ShaderID for the FlareOcclusionTex</param> 617 /// <param name="_FlareCloudOpacity">ShaderID for the FlareCloudOpacity</param> 618 /// <param name="_FlareOcclusionIndex">ShaderID for the FlareOcclusionIndex</param> 619 /// <param name="_FlareTex">ShaderID for the FlareTex</param> 620 /// <param name="_FlareColorValue">ShaderID for the FlareColor</param> 621 /// <param name="_FlareSunOcclusionTex">ShaderID for the _FlareSunOcclusionTex</param> 622 /// <param name="_FlareData0">ShaderID for the FlareData0</param> 623 /// <param name="_FlareData1">ShaderID for the FlareData1</param> 624 /// <param name="_FlareData2">ShaderID for the FlareData2</param> 625 /// <param name="_FlareData3">ShaderID for the FlareData3</param> 626 /// <param name="_FlareData4">ShaderID for the FlareData4</param> 627 [Obsolete("Use ComputeOcclusion without _FlareOcclusionTex.._FlareData4 parameters.")] 628 static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass xr, int xrIndex, 629 float actualWidth, float actualHeight, 630 bool usePanini, float paniniDistance, float paniniCropToFit, bool isCameraRelative, 631 Vector3 cameraPositionWS, 632 Matrix4x4 viewProjMatrix, 633 UnsafeCommandBuffer cmd, 634 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture, 635 int _FlareOcclusionTex, int _FlareCloudOpacity, int _FlareOcclusionIndex, int _FlareTex, int _FlareColorValue, int _FlareSunOcclusionTex, int _FlareData0, int _FlareData1, int _FlareData2, int _FlareData3, int _FlareData4) 636 { 637 ComputeOcclusion( 638 lensFlareShader, cam, xr, xrIndex, 639 actualWidth, actualHeight, 640 usePanini, paniniDistance, paniniCropToFit, isCameraRelative, 641 cameraPositionWS, 642 viewProjMatrix, 643 cmd.m_WrappedCommandBuffer, 644 taaEnabled, hasCloudLayer, cloudOpacityTexture, sunOcclusionTexture, 645 _FlareOcclusionTex, _FlareCloudOpacity, _FlareOcclusionIndex, _FlareTex, _FlareColorValue, _FlareSunOcclusionTex, _FlareData0, _FlareData1, _FlareData2, _FlareData3, _FlareData4); 646 } 647 648 /// <summary> 649 /// Effective Job of drawing the set of Lens Flare registered 650 /// </summary> 651 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 652 /// <param name="cam">Camera</param> 653 /// <param name="xr">XRPass data.</param> 654 /// <param name="xrIndex">XR multipass ID.</param> 655 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 656 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 657 /// <param name="usePanini">Set if use Panani Projection</param> 658 /// <param name="paniniDistance">Distance used for Panini projection</param> 659 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 660 /// <param name="isCameraRelative">Set if camera is relative</param> 661 /// <param name="cameraPositionWS">Camera World Space position</param> 662 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 663 /// <param name="cmd">Command Buffer</param> 664 /// <param name="taaEnabled">Set if TAA is enabled</param> 665 /// <param name="hasCloudLayer">Unused</param> 666 /// <param name="cloudOpacityTexture">Unused</param> 667 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 668 static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass xr, int xrIndex, 669 float actualWidth, float actualHeight, 670 bool usePanini, float paniniDistance, float paniniCropToFit, bool isCameraRelative, 671 Vector3 cameraPositionWS, 672 Matrix4x4 viewProjMatrix, 673 UnsafeCommandBuffer cmd, 674 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture) 675 { 676 ComputeOcclusion( 677 lensFlareShader, cam, xr, xrIndex, 678 actualWidth, actualHeight, 679 usePanini, paniniDistance, paniniCropToFit, isCameraRelative, 680 cameraPositionWS, 681 viewProjMatrix, 682 cmd.m_WrappedCommandBuffer, 683 taaEnabled, hasCloudLayer, cloudOpacityTexture, sunOcclusionTexture); 684 } 685 686 /// <summary> 687 /// Effective Job of drawing the set of Lens Flare registered 688 /// </summary> 689 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 690 /// <param name="cam">Camera</param> 691 /// <param name="xr">XRPass data.</param> 692 /// <param name="xrIndex">XR multipass ID.</param> 693 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 694 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 695 /// <param name="usePanini">Set if use Panani Projection</param> 696 /// <param name="paniniDistance">Distance used for Panini projection</param> 697 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 698 /// <param name="isCameraRelative">Set if camera is relative</param> 699 /// <param name="cameraPositionWS">Camera World Space position</param> 700 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 701 /// <param name="cmd">Command Buffer</param> 702 /// <param name="taaEnabled">Set if TAA is enabled</param> 703 /// <param name="hasCloudLayer">Unused</param> 704 /// <param name="cloudOpacityTexture">Unused</param> 705 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 706 /// <param name="_FlareOcclusionTex">ShaderID for the FlareOcclusionTex</param> 707 /// <param name="_FlareCloudOpacity">ShaderID for the FlareCloudOpacity</param> 708 /// <param name="_FlareOcclusionIndex">ShaderID for the FlareOcclusionIndex</param> 709 /// <param name="_FlareTex">ShaderID for the FlareTex</param> 710 /// <param name="_FlareColorValue">ShaderID for the FlareColor</param> 711 /// <param name="_FlareSunOcclusionTex">ShaderID for the _FlareSunOcclusionTex</param> 712 /// <param name="_FlareData0">ShaderID for the FlareData0</param> 713 /// <param name="_FlareData1">ShaderID for the FlareData1</param> 714 /// <param name="_FlareData2">ShaderID for the FlareData2</param> 715 /// <param name="_FlareData3">ShaderID for the FlareData3</param> 716 /// <param name="_FlareData4">ShaderID for the FlareData4</param> 717 [Obsolete("Use ComputeOcclusion without _FlareOcclusionTex.._FlareData4 parameters.")] 718 static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass xr, int xrIndex, 719 float actualWidth, float actualHeight, 720 bool usePanini, float paniniDistance, float paniniCropToFit, bool isCameraRelative, 721 Vector3 cameraPositionWS, 722 Matrix4x4 viewProjMatrix, 723 Rendering.CommandBuffer cmd, 724 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture, 725 int _FlareOcclusionTex, int _FlareCloudOpacity, int _FlareOcclusionIndex, int _FlareTex, int _FlareColorValue, int _FlareSunOcclusionTex, int _FlareData0, int _FlareData1, int _FlareData2, int _FlareData3, int _FlareData4) 726 { 727 ComputeOcclusion(lensFlareShader, cam, xr, xrIndex, 728 actualWidth, actualHeight, 729 usePanini, paniniDistance, paniniCropToFit, isCameraRelative, 730 cameraPositionWS, 731 viewProjMatrix, 732 cmd, 733 taaEnabled, hasCloudLayer, cloudOpacityTexture, sunOcclusionTexture); 734 } 735 736 static bool ForceSingleElement(LensFlareDataElementSRP element) 737 { 738 return !element.allowMultipleElement 739 || element.count == 1 740 || element.flareType == SRPLensFlareType.Ring; 741 } 742 743 /// <summary> 744 /// Effective Job of drawing the set of Lens Flare registered 745 /// </summary> 746 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 747 /// <param name="cam">Camera</param> 748 /// <param name="xr">XRPass data.</param> 749 /// <param name="xrIndex">XR multipass ID.</param> 750 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 751 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 752 /// <param name="usePanini">Set if use Panani Projection</param> 753 /// <param name="paniniDistance">Distance used for Panini projection</param> 754 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 755 /// <param name="isCameraRelative">Set if camera is relative</param> 756 /// <param name="cameraPositionWS">Camera World Space position</param> 757 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 758 /// <param name="cmd">Command Buffer</param> 759 /// <param name="taaEnabled">Set if TAA is enabled</param> 760 /// <param name="hasCloudLayer">Unused</param> 761 /// <param name="cloudOpacityTexture">Unused</param> 762 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 763 static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass xr, int xrIndex, 764 float actualWidth, float actualHeight, 765 bool usePanini, float paniniDistance, float paniniCropToFit, bool isCameraRelative, 766 Vector3 cameraPositionWS, 767 Matrix4x4 viewProjMatrix, 768 Rendering.CommandBuffer cmd, 769 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture) 770 { 771 if (!IsOcclusionRTCompatible()) 772 return; 773 774 xr.StopSinglePass(cmd); 775 776#if UNITY_EDITOR 777 bool inPrefabStage = IsPrefabStageEnabled(); 778 UnityEditor.SceneManagement.PrefabStage prefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage(); 779 GameObject prefabGameObject = null; 780 LensFlareComponentSRP[] prefabStageLensFlares = null; 781 if (prefabStage != null) 782 { 783 prefabGameObject = prefabStage.prefabContentsRoot; 784 if (prefabGameObject == null) 785 return; 786 prefabStageLensFlares = GetLensFlareComponents(prefabGameObject); 787 if (prefabStageLensFlares.Length == 0) 788 { 789 return; 790 } 791 } 792#endif 793 794 if (Instance.IsEmpty()) 795 return; 796 797#if UNITY_EDITOR 798 if (cam.cameraType == CameraType.SceneView) 799 { 800 // Determine whether the "Animated Materials" checkbox is checked for the current view. 801 for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++) // Using a foreach on an ArrayList generates garbage ... 802 { 803 var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView; 804 if (sv.camera == cam && !sv.sceneViewState.flaresEnabled) 805 { 806 return; 807 } 808 } 809 } 810#endif 811 812 Vector2 screenSize = new Vector2(actualWidth, actualHeight); 813 float screenRatio = screenSize.x / screenSize.y; 814 Vector2 vScreenRatio = new Vector2(screenRatio, 1.0f); 815 816#if ENABLE_VR && ENABLE_XR_MODULE 817 if (xr.enabled && xr.singlePassEnabled) 818 { 819 CoreUtils.SetRenderTarget(cmd, occlusionRT, depthSlice: xrIndex); 820 cmd.SetGlobalInt(_ViewId, xrIndex); 821 } 822 else 823#endif 824 { 825 CoreUtils.SetRenderTarget(cmd, occlusionRT); 826 if (xr.enabled) // multipass 827 cmd.SetGlobalInt(_ViewId, xr.multipassId); 828 else 829 cmd.SetGlobalInt(_ViewId, -1); 830 } 831 832 if (!taaEnabled) 833 { 834 cmd.ClearRenderTarget(false, true, Color.black); 835 } 836 837 float dx = 1.0f / ((float)maxLensFlareWithOcclusion); 838 float dy = 1.0f / ((float)(maxLensFlareWithOcclusionTemporalSample + mergeNeeded)); 839 float halfx = 0.5f / ((float)maxLensFlareWithOcclusion); 840 float halfy = 0.5f / ((float)(maxLensFlareWithOcclusionTemporalSample + mergeNeeded)); 841 842 foreach (LensFlareCompInfo info in m_Data) 843 { 844 if (info == null || info.comp == null) 845 continue; 846 847 LensFlareComponentSRP comp = info.comp; 848 LensFlareDataSRP data = comp.lensFlareData; 849 850 if (IsLensFlareSRPHidden(cam, comp, data) || 851 !comp.useOcclusion || 852 (comp.useOcclusion && comp.sampleCount == 0)) 853 continue; 854 855#if UNITY_EDITOR 856 if (inPrefabStage && !IsCurrentPrefabLensFlareComponent(prefabGameObject, prefabStageLensFlares, comp)) 857 { 858 continue; 859 } 860#endif 861 862 Light light = null; 863 if (!comp.TryGetComponent<Light>(out light)) 864 light = null; 865 866 Vector3 positionWS; 867 Vector3 viewportPos; 868 869 bool isDirLight = false; 870 if (light != null && light.type == LightType.Directional) 871 { 872 positionWS = -light.transform.forward * cam.farClipPlane; 873 isDirLight = true; 874 } 875 else 876 { 877 positionWS = comp.transform.position; 878 } 879 880 viewportPos = WorldToViewport(cam, !isDirLight, isCameraRelative, viewProjMatrix, positionWS); 881 882 if (usePanini && cam == Camera.main) 883 { 884 viewportPos = DoPaniniProjection(viewportPos, actualWidth, actualHeight, cam.fieldOfView, paniniCropToFit, paniniDistance); 885 } 886 887 if (viewportPos.z < 0.0f) 888 continue; 889 890 if (!comp.allowOffScreen) 891 { 892 if (viewportPos.x < 0.0f || viewportPos.x > 1.0f || 893 viewportPos.y < 0.0f || viewportPos.y > 1.0f) 894 continue; 895 } 896 897 Vector3 diffToObject = positionWS - cameraPositionWS; 898 // Check if the light is forward, can be an issue with, 899 // the math associated to Panini projection 900 if (Vector3.Dot(cam.transform.forward, diffToObject) < 0.0f) 901 { 902 continue; 903 } 904 float distToObject = diffToObject.magnitude; 905 float coefDistSample = distToObject / comp.maxAttenuationDistance; 906 float coefScaleSample = distToObject / comp.maxAttenuationScale; 907 float distanceAttenuation = !isDirLight && comp.distanceAttenuationCurve.length > 0 ? comp.distanceAttenuationCurve.Evaluate(coefDistSample) : 1.0f; 908 float scaleByDistance = !isDirLight && comp.scaleByDistanceCurve.length >= 1 ? comp.scaleByDistanceCurve.Evaluate(coefScaleSample) : 1.0f; 909 910 Vector3 dir; 911 if (isDirLight) 912 dir = comp.transform.forward; 913 else 914 dir = (cam.transform.position - comp.transform.position).normalized; 915 Vector3 screenPosZ = WorldToViewport(cam, !isDirLight, isCameraRelative, viewProjMatrix, positionWS + dir * comp.occlusionOffset); 916 917 float adjustedOcclusionRadius = isDirLight ? comp.celestialProjectedOcclusionRadius(cam) : comp.occlusionRadius; 918 Vector2 occlusionRadiusEdgeScreenPos0 = (Vector2)viewportPos; 919 Vector2 occlusionRadiusEdgeScreenPos1 = (Vector2)WorldToViewport(cam, !isDirLight, isCameraRelative, viewProjMatrix, positionWS + cam.transform.up * adjustedOcclusionRadius); 920 float occlusionRadius = (occlusionRadiusEdgeScreenPos1 - occlusionRadiusEdgeScreenPos0).magnitude; 921 922 cmd.SetGlobalVector(_FlareData1, new Vector4(occlusionRadius, comp.sampleCount, screenPosZ.z, actualHeight / actualWidth)); 923 924 SetOcclusionPermutation(cmd, comp.environmentOcclusion, _FlareSunOcclusionTex, sunOcclusionTexture); 925 cmd.EnableShaderKeyword("FLARE_COMPUTE_OCCLUSION"); 926 927 Vector2 screenPos = new Vector2(2.0f * viewportPos.x - 1.0f, -(2.0f * viewportPos.y - 1.0f)); 928 if (!SystemInfo.graphicsUVStartsAtTop && isDirLight) 929 screenPos.y = -screenPos.y; 930 931 Vector2 radPos = new Vector2(Mathf.Abs(screenPos.x), Mathf.Abs(screenPos.y)); 932 float radius = Mathf.Max(radPos.x, radPos.y); // l1 norm (instead of l2 norm) 933 float radialsScaleRadius = comp.radialScreenAttenuationCurve.length > 0 ? comp.radialScreenAttenuationCurve.Evaluate(radius) : 1.0f; 934 935 float compIntensity = comp.intensity * radialsScaleRadius * distanceAttenuation; 936 937 if (compIntensity <= 0.0f) 938 continue; 939 940 float globalCos0 = Mathf.Cos(0.0f); 941 float globalSin0 = Mathf.Sin(0.0f); 942 943 float position = 0.0f; 944 945 float usedGradientPosition = Mathf.Clamp01(1.0f - 1e-6f); 946 947 cmd.SetGlobalVector(_FlareData3, new Vector4(comp.allowOffScreen ? 1.0f : -1.0f, usedGradientPosition, Mathf.Exp(Mathf.Lerp(0.0f, 4.0f, 1.0f)), 1.0f / 3.0f)); 948 949 Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0, vScreenRatio); 950 Vector4 flareData0 = GetFlareData0(screenPos, Vector2.one, rayOff, vScreenRatio, 0.0f, position, 0.0f, Vector2.zero, false); 951 952 cmd.SetGlobalVector(_FlareData0, flareData0); 953 cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, 0.0f, 0.0f)); 954 955 Rect rect; 956 if (taaEnabled) 957 rect = new Rect() { x = info.index, y = frameIdx + mergeNeeded, width = 1, height = 1 }; 958 else 959 rect = new Rect() { x = info.index, y = 0, width = 1, height = 1 }; 960 cmd.SetViewport(rect); 961 962 Blitter.DrawQuad(cmd, lensFlareShader, lensFlareShader.FindPass("LensFlareOcclusion")); 963 } 964 965 // Clear the remaining buffer if not TAA the whole OcclusionRT is already cleared 966 if (taaEnabled) 967 { 968 CoreUtils.SetRenderTarget(cmd, occlusionRT, depthSlice: xrIndex); 969 cmd.SetViewport(new Rect() { x = m_Data.Count, y = 0, width = (maxLensFlareWithOcclusion - m_Data.Count), height = (maxLensFlareWithOcclusionTemporalSample + mergeNeeded) }); 970 cmd.ClearRenderTarget(false, true, Color.black); 971 } 972 973 ++frameIdx; 974 frameIdx %= maxLensFlareWithOcclusionTemporalSample; 975 976 xr.StartSinglePass(cmd); 977 } 978 979 /// <summary> 980 /// Function that process a single element of a LensFlareDataSRP, this function is used on scene/game view and on the inspector for the thumbnail. 981 /// </summary> 982 /// <param name="element">Single LensFlare asset we need to process.</param> 983 /// <param name="cmd">Command Buffer.</param> 984 /// <param name="globalColorModulation">Color Modulation from Component?</param> 985 /// <param name="light">Light used for the modulation of this singe element.</param> 986 /// <param name="compIntensity">Intensity from Component.</param> 987 /// <param name="scale">Scale from component</param> 988 /// <param name="lensFlareShader">Shader used on URP or HDRP.</param> 989 /// <param name="screenPos">Screen Position</param> 990 /// <param name="compAllowOffScreen">Allow Lens Flare offscreen</param> 991 /// <param name="vScreenRatio">Screen Ratio</param> 992 /// <param name="flareData1">_FlareData1 used internally by the shader.</param> 993 /// <param name="preview">true if we are on preview on the inspector</param> 994 /// <param name="depth">Depth counter for recursive call of 'ProcessLensFlareSRPElementsSingle'.</param> 995 public static void ProcessLensFlareSRPElementsSingle(LensFlareDataElementSRP element, Rendering.CommandBuffer cmd, Color globalColorModulation, Light light, 996 float compIntensity, float scale, Material lensFlareShader, Vector2 screenPos, bool compAllowOffScreen, Vector2 vScreenRatio, Vector4 flareData1, bool preview, int depth) 997 { 998 if (element == null || 999 element.visible == false || 1000 (element.lensFlareTexture == null && element.flareType == SRPLensFlareType.Image) || 1001 element.localIntensity <= 0.0f || 1002 element.count <= 0 || 1003 (element.flareType == SRPLensFlareType.LensFlareDataSRP && element.lensFlareDataSRP == null)) 1004 return; 1005 1006 if (element.flareType == SRPLensFlareType.LensFlareDataSRP && element.lensFlareDataSRP != null) 1007 { 1008 ProcessLensFlareSRPElements(ref element.lensFlareDataSRP.elements, cmd, globalColorModulation, light, compIntensity, scale, lensFlareShader, screenPos, compAllowOffScreen, vScreenRatio, flareData1, preview, depth + 1); 1009 return; 1010 } 1011 1012 Color colorModulation = globalColorModulation; 1013 if (light != null && element.modulateByLightColor) 1014 { 1015 if (light.useColorTemperature) 1016 colorModulation *= light.color * Mathf.CorrelatedColorTemperatureToRGB(light.colorTemperature); 1017 else 1018 colorModulation *= light.color; 1019 } 1020 1021 Color curColor = colorModulation; 1022 1023 float currentIntensity = element.localIntensity * compIntensity; 1024 1025 if (currentIntensity <= 0.0f) 1026 return; 1027 1028 Texture texture = element.lensFlareTexture; 1029 float usedAspectRatio; 1030 if (element.flareType == SRPLensFlareType.Image) 1031 usedAspectRatio = element.preserveAspectRatio ? ((((float)texture.height) / (float)texture.width)) : 1.0f; 1032 else 1033 usedAspectRatio = 1.0f; 1034 1035 float rotation = element.rotation; 1036 1037 Vector2 elemSizeXY; 1038 if (element.preserveAspectRatio) 1039 { 1040 if (usedAspectRatio >= 1.0f) 1041 { 1042 elemSizeXY = new Vector2(element.sizeXY.x / usedAspectRatio, element.sizeXY.y); 1043 } 1044 else 1045 { 1046 elemSizeXY = new Vector2(element.sizeXY.x, element.sizeXY.y * usedAspectRatio); 1047 } 1048 } 1049 else 1050 { 1051 elemSizeXY = new Vector2(element.sizeXY.x, element.sizeXY.y); 1052 } 1053 float scaleSize = 0.1f; // Arbitrary value 1054 Vector2 size = new Vector2(elemSizeXY.x, elemSizeXY.y); 1055 float combinedScale = scaleSize * element.uniformScale * scale; 1056 size *= combinedScale; 1057 1058 curColor *= element.tint; 1059 1060 float angularOffset = SystemInfo.graphicsUVStartsAtTop ? element.angularOffset : -element.angularOffset; 1061 float globalCos0 = Mathf.Cos(-angularOffset * Mathf.Deg2Rad); 1062 float globalSin0 = Mathf.Sin(-angularOffset * Mathf.Deg2Rad); 1063 1064 float position = 2.0f * element.position; 1065 1066 SRPLensFlareBlendMode blendMode = element.blendMode; 1067 int materialPass; 1068#if UNITY_EDITOR 1069 if (!preview) 1070#endif 1071 { 1072 if (blendMode == SRPLensFlareBlendMode.Additive) 1073 materialPass = lensFlareShader.FindPass("LensFlareAdditive"); 1074 else if (blendMode == SRPLensFlareBlendMode.Screen) 1075 materialPass = lensFlareShader.FindPass("LensFlareScreen"); 1076 else if (blendMode == SRPLensFlareBlendMode.Premultiply) 1077 materialPass = lensFlareShader.FindPass("LensFlarePremultiply"); 1078 else if (blendMode == SRPLensFlareBlendMode.Lerp) 1079 materialPass = lensFlareShader.FindPass("LensFlareLerp"); 1080 else 1081 materialPass = lensFlareShader.FindPass("LensFlareOcclusion"); 1082 } 1083#if UNITY_EDITOR 1084 else 1085 { 1086 if (element.inverseSDF) 1087 materialPass = lensFlareShader.FindPass("FlarePreviewInverted"); 1088 else 1089 materialPass = lensFlareShader.FindPass("FlarePreviewNotInverted"); 1090 } 1091#endif 1092 1093 flareData1.x = (float)element.flareType; 1094 if (ForceSingleElement(element)) 1095 cmd.SetGlobalVector(_FlareData1, flareData1); 1096 1097 if (element.flareType == SRPLensFlareType.Circle || 1098 element.flareType == SRPLensFlareType.Polygon || 1099 element.flareType == SRPLensFlareType.Ring) 1100 { 1101 if (element.inverseSDF) 1102 { 1103 cmd.EnableShaderKeyword("FLARE_INVERSE_SDF"); 1104 } 1105 else 1106 { 1107 cmd.DisableShaderKeyword("FLARE_INVERSE_SDF"); 1108 } 1109 } 1110 else 1111 { 1112 cmd.DisableShaderKeyword("FLARE_INVERSE_SDF"); 1113 } 1114 1115 if (element.lensFlareTexture != null) 1116 cmd.SetGlobalTexture(_FlareTex, element.lensFlareTexture); 1117 1118 if (element.tintColorType != SRPLensFlareColorType.Constant) 1119 cmd.SetGlobalTexture(_FlareRadialTint, element.tintGradient.GetTexture()); 1120 1121 float usedGradientPosition = Mathf.Clamp01((1.0f - element.edgeOffset) - 1e-6f); 1122 if (element.flareType == SRPLensFlareType.Polygon) 1123 usedGradientPosition = Mathf.Pow(usedGradientPosition + 1.0f, 5); 1124 1125 Vector2 ComputeLocalSize(Vector2 rayOff, Vector2 rayOff0, Vector2 curSize, AnimationCurve distortionCurve) 1126 { 1127 Vector2 rayOffZ = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0, vScreenRatio); 1128 Vector2 localRadPos; 1129 float localRadius; 1130 if (!element.distortionRelativeToCenter) 1131 { 1132 localRadPos = (rayOff - rayOff0) * 0.5f; 1133 localRadius = Mathf.Clamp01(Mathf.Max(Mathf.Abs(localRadPos.x), Mathf.Abs(localRadPos.y))); // l1 norm (instead of l2 norm) 1134 } 1135 else 1136 { 1137 localRadPos = screenPos + (rayOff + new Vector2(element.positionOffset.x, -element.positionOffset.y)) * element.translationScale; 1138 localRadius = Mathf.Clamp01(localRadPos.magnitude); // l2 norm (instead of l1 norm) 1139 } 1140 1141 float localLerpValue = Mathf.Clamp01(distortionCurve.Evaluate(localRadius)); 1142 return new Vector2(Mathf.Lerp(curSize.x, element.targetSizeDistortion.x * combinedScale / usedAspectRatio, localLerpValue), 1143 Mathf.Lerp(curSize.y, element.targetSizeDistortion.y * combinedScale, localLerpValue)); 1144 } 1145 1146 float usedSDFRoundness = element.sdfRoundness; 1147 1148 Vector4 data3 = 1149 new Vector4(compAllowOffScreen ? 1.0f : -1.0f, 1150 usedGradientPosition, 1151 Mathf.Exp(Mathf.Lerp(0.0f, 4.0f, Mathf.Clamp01(1.0f - element.fallOff))), 1152 element.flareType == SRPLensFlareType.Ring ? element.ringThickness : 1.0f / (float)element.sideCount); 1153 cmd.SetGlobalVector(_FlareData3, data3); 1154 if (element.flareType == SRPLensFlareType.Polygon) 1155 { 1156 float invSide = 1.0f / (float)element.sideCount; 1157 float rCos = Mathf.Cos(Mathf.PI * invSide); 1158 float roundValue = rCos * usedSDFRoundness; 1159 float r = rCos - roundValue; 1160 float an = 2.0f * Mathf.PI * invSide; 1161 float he = r * Mathf.Tan(0.5f * an); 1162 cmd.SetGlobalVector(_FlareData4, new Vector4(usedSDFRoundness, r, an, he)); 1163 } 1164 else if (element.flareType == SRPLensFlareType.Ring) 1165 { 1166 cmd.SetGlobalVector(_FlareData4, new Vector4(element.noiseAmplitude, element.noiseFrequency, element.noiseSpeed, 0.0f)); 1167 } 1168 else 1169 { 1170 cmd.SetGlobalVector(_FlareData4, new Vector4(usedSDFRoundness, 0.0f, 0.0f, 0.0f)); 1171 } 1172 1173 cmd.SetGlobalVector(_FlareData5, new Vector4((float)(element.tintColorType), currentIntensity, element.shapeCutOffSpeed, element.shapeCutOffRadius)); 1174 if (ForceSingleElement(element)) 1175 { 1176 Vector2 localSize = size; 1177 Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0, vScreenRatio); 1178 if (element.enableRadialDistortion) 1179 { 1180 Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0, vScreenRatio); 1181 localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); 1182 } 1183 Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, rayOff, vScreenRatio, rotation, position, angularOffset, element.positionOffset, element.autoRotate); 1184 1185 cmd.SetGlobalVector(_FlareData0, flareData0); 1186 cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); 1187 cmd.SetGlobalVector(_FlareColorValue, curColor); 1188 1189 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); 1190 } 1191 else 1192 { 1193 float dLength = 2.0f * element.lengthSpread / ((float)(element.count - 1)); 1194 1195 if (element.distribution == SRPLensFlareDistribution.Uniform) 1196 { 1197 float uniformAngle = 0.0f; 1198 for (int elemIdx = 0; elemIdx < element.count; ++elemIdx) 1199 { 1200 Vector2 localSize = size; 1201 Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0, vScreenRatio); 1202 if (element.enableRadialDistortion) 1203 { 1204 Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0, vScreenRatio); 1205 localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); 1206 } 1207 1208 float timeScale = element.count >= 2 ? ((float)elemIdx) / ((float)(element.count - 1)) : 0.5f; 1209 1210 Color col = element.colorGradient.Evaluate(timeScale); 1211 1212 Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, rayOff, vScreenRatio, rotation + uniformAngle, position, angularOffset, element.positionOffset, element.autoRotate); 1213 cmd.SetGlobalVector(_FlareData0, flareData0); 1214 1215 flareData1.y = (float)elemIdx; 1216 cmd.SetGlobalVector(_FlareData1, flareData1); 1217 cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); 1218 cmd.SetGlobalVector(_FlareColorValue, curColor * col); 1219 1220 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); 1221 position += dLength; 1222 uniformAngle += element.uniformAngle; 1223 } 1224 } 1225 else if (element.distribution == SRPLensFlareDistribution.Random) 1226 { 1227 Random.State backupRandState = UnityEngine.Random.state; 1228 Random.InitState(element.seed); 1229 Vector2 side = new Vector2(globalSin0, globalCos0); 1230 side *= element.positionVariation.y; 1231 float RandomRange(float min, float max) 1232 { 1233 return Random.Range(min, max); 1234 } 1235 1236 for (int elemIdx = 0; elemIdx < element.count; ++elemIdx) 1237 { 1238 float localIntensity = RandomRange(-1.0f, 1.0f) * element.intensityVariation + 1.0f; 1239 1240 Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0, vScreenRatio); 1241 Vector2 localSize = size; 1242 if (element.enableRadialDistortion) 1243 { 1244 Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0, vScreenRatio); 1245 localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); 1246 } 1247 1248 localSize += localSize * (element.scaleVariation * RandomRange(-1.0f, 1.0f)); 1249 1250 Color randCol = element.colorGradient.Evaluate(RandomRange(0.0f, 1.0f)); 1251 1252 Vector2 localPositionOffset = element.positionOffset + RandomRange(-1.0f, 1.0f) * side; 1253 1254 float localRotation = rotation + RandomRange(-Mathf.PI, Mathf.PI) * element.rotationVariation; 1255 1256 if (localIntensity > 0.0f) 1257 { 1258 Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, rayOff, vScreenRatio, localRotation, position, angularOffset, localPositionOffset, element.autoRotate); 1259 cmd.SetGlobalVector(_FlareData0, flareData0); 1260 flareData1.y = (float)elemIdx; 1261 cmd.SetGlobalVector(_FlareData1, flareData1); 1262 cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); 1263 cmd.SetGlobalVector(_FlareColorValue, curColor * randCol * localIntensity); 1264 1265 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); 1266 } 1267 1268 position += dLength; 1269 position += 0.5f * dLength * RandomRange(-1.0f, 1.0f) * element.positionVariation.x; 1270 } 1271 Random.state = backupRandState; 1272 } 1273 else if (element.distribution == SRPLensFlareDistribution.Curve) 1274 { 1275 for (int elemIdx = 0; elemIdx < element.count; ++elemIdx) 1276 { 1277 float timeScale = element.count >= 2 ? ((float)elemIdx) / ((float)(element.count - 1)) : 0.5f; 1278 1279 Color col = element.colorGradient.Evaluate(timeScale); 1280 1281 float positionSpacing = element.positionCurve.length > 0 ? element.positionCurve.Evaluate(timeScale) : 1.0f; 1282 1283 float localPos = position + 2.0f * element.lengthSpread * positionSpacing; 1284 Vector2 rayOff = GetLensFlareRayOffset(screenPos, localPos, globalCos0, globalSin0, vScreenRatio); 1285 Vector2 localSize = size; 1286 if (element.enableRadialDistortion) 1287 { 1288 Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0, vScreenRatio); 1289 localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); 1290 } 1291 float sizeCurveValue = element.scaleCurve.length > 0 ? element.scaleCurve.Evaluate(timeScale) : 1.0f; 1292 localSize *= sizeCurveValue; 1293 1294 float angleFromCurve = element.uniformAngleCurve.Evaluate(timeScale) * (180.0f - (180.0f / (float)element.count)); 1295 1296 Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, rayOff, vScreenRatio, rotation + angleFromCurve, localPos, angularOffset, element.positionOffset, element.autoRotate); 1297 cmd.SetGlobalVector(_FlareData0, flareData0); 1298 flareData1.y = (float)elemIdx; 1299 cmd.SetGlobalVector(_FlareData1, flareData1); 1300 cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); 1301 cmd.SetGlobalVector(_FlareColorValue, curColor * col); 1302 1303 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); 1304 } 1305 } 1306 } 1307 } 1308 1309 static void ProcessLensFlareSRPElements(ref LensFlareDataElementSRP[] elements, Rendering.CommandBuffer cmd, Color globalColorModulation, Light light, 1310 float compIntensity, float scale, Material lensFlareShader, Vector2 screenPos, bool compAllowOffScreen, Vector2 vScreenRatio, Vector4 flareData1, bool preview, int depth) 1311 { 1312 if (depth > 16) 1313 { 1314 Debug.LogWarning("LensFlareSRPAsset contains too deep recursive asset (> 16). Be careful to not have recursive aggregation, A contains B, B contains A, ... which will produce an infinite loop."); 1315 return; 1316 } 1317 1318 foreach (LensFlareDataElementSRP element in elements) 1319 { 1320 ProcessLensFlareSRPElementsSingle(element, cmd, globalColorModulation, light, compIntensity, scale, lensFlareShader, screenPos, compAllowOffScreen, vScreenRatio, flareData1, preview, depth); 1321 } 1322 } 1323 1324 /// <summary> 1325 /// Effective Job of drawing the set of Lens Flare registered 1326 /// </summary> 1327 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 1328 /// <param name="cam">Camera</param> 1329 /// <param name="viewport">Viewport used for rendering and XR applied.</param> 1330 /// <param name="xr">XRPass data.</param> 1331 /// <param name="xrIndex">XR multipass ID.</param> 1332 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 1333 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 1334 /// <param name="usePanini">Set if use Panani Projection</param> 1335 /// <param name="paniniDistance">Distance used for Panini projection</param> 1336 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 1337 /// <param name="isCameraRelative">Set if camera is relative</param> 1338 /// <param name="cameraPositionWS">Camera World Space position</param> 1339 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 1340 /// <param name="cmd">Command Buffer</param> 1341 /// <param name="taaEnabled">Set if TAA is enabled</param> 1342 /// <param name="hasCloudLayer">Unused</param> 1343 /// <param name="cloudOpacityTexture">Unused</param> 1344 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 1345 /// <param name="colorBuffer">Source Render Target which contains the Color Buffer</param> 1346 /// <param name="GetLensFlareLightAttenuation">Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP</param> 1347 /// <param name="_FlareOcclusionTex">ShaderID for the FlareOcclusionTex</param> 1348 /// <param name="_FlareOcclusionIndex">ShaderID for the FlareOcclusionIndex</param> 1349 /// <param name="_FlareOcclusionRemapTex">ShaderID for the OcclusionRemap</param> 1350 /// <param name="_FlareCloudOpacity">ShaderID for the FlareCloudOpacity</param> 1351 /// <param name="_FlareSunOcclusionTex">ShaderID for the _FlareSunOcclusionTex</param> 1352 /// <param name="_FlareTex">ShaderID for the FlareTex</param> 1353 /// <param name="_FlareColorValue">ShaderID for the FlareColor</param> 1354 /// <param name="_FlareData0">ShaderID for the FlareData0</param> 1355 /// <param name="_FlareData1">ShaderID for the FlareData1</param> 1356 /// <param name="_FlareData2">ShaderID for the FlareData2</param> 1357 /// <param name="_FlareData3">ShaderID for the FlareData3</param> 1358 /// <param name="_FlareData4">ShaderID for the FlareData4</param> 1359 /// <param name="debugView">Debug View which setup black background to see only Lens Flare</param> 1360 [Obsolete("Use DoLensFlareDataDrivenCommon without _FlareOcclusionRemapTex.._FlareData4 parameters.")] 1361 static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, 1362 float actualWidth, float actualHeight, 1363 bool usePanini, float paniniDistance, float paniniCropToFit, 1364 bool isCameraRelative, 1365 Vector3 cameraPositionWS, 1366 Matrix4x4 viewProjMatrix, 1367 UnsafeCommandBuffer cmd, 1368 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture, 1369 Rendering.RenderTargetIdentifier colorBuffer, 1370 System.Func<Light, Camera, Vector3, float> GetLensFlareLightAttenuation, 1371 int _FlareOcclusionRemapTex, int _FlareOcclusionTex, int _FlareOcclusionIndex, 1372 int _FlareCloudOpacity, int _FlareSunOcclusionTex, 1373 int _FlareTex, int _FlareColorValue, int _FlareData0, int _FlareData1, int _FlareData2, int _FlareData3, int _FlareData4, 1374 bool debugView) 1375 { 1376 DoLensFlareDataDrivenCommon(lensFlareShader, cam, viewport, xr, xrIndex, 1377 actualWidth, actualHeight, 1378 usePanini, paniniDistance, paniniCropToFit, 1379 isCameraRelative, 1380 cameraPositionWS, 1381 viewProjMatrix, 1382 cmd, 1383 taaEnabled, hasCloudLayer, cloudOpacityTexture, sunOcclusionTexture, 1384 colorBuffer, 1385 GetLensFlareLightAttenuation, 1386 debugView); 1387 } 1388 1389 /// <summary> 1390 /// Effective Job of drawing the set of Lens Flare registered 1391 /// </summary> 1392 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 1393 /// <param name="cam">Camera</param> 1394 /// <param name="viewport">Viewport used for rendering and XR applied.</param> 1395 /// <param name="xr">XRPass data.</param> 1396 /// <param name="xrIndex">XR multipass ID.</param> 1397 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 1398 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 1399 /// <param name="usePanini">Set if use Panani Projection</param> 1400 /// <param name="paniniDistance">Distance used for Panini projection</param> 1401 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 1402 /// <param name="isCameraRelative">Set if camera is relative</param> 1403 /// <param name="cameraPositionWS">Camera World Space position</param> 1404 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 1405 /// <param name="cmd">Command Buffer</param> 1406 /// <param name="taaEnabled">Set if TAA is enabled</param> 1407 /// <param name="hasCloudLayer">Unused</param> 1408 /// <param name="cloudOpacityTexture">Unused</param> 1409 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 1410 /// <param name="colorBuffer">Source Render Target which contains the Color Buffer</param> 1411 /// <param name="GetLensFlareLightAttenuation">Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP</param> 1412 /// <param name="debugView">Debug View which setup black background to see only Lens Flare</param> 1413 static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, 1414 float actualWidth, float actualHeight, 1415 bool usePanini, float paniniDistance, float paniniCropToFit, 1416 bool isCameraRelative, 1417 Vector3 cameraPositionWS, 1418 Matrix4x4 viewProjMatrix, 1419 UnsafeCommandBuffer cmd, 1420 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture, 1421 Rendering.RenderTargetIdentifier colorBuffer, 1422 System.Func<Light, Camera, Vector3, float> GetLensFlareLightAttenuation, 1423 bool debugView) 1424 { 1425 DoLensFlareDataDrivenCommon(lensFlareShader, cam, viewport, xr, xrIndex, 1426 actualWidth, actualHeight, 1427 usePanini, paniniDistance, paniniCropToFit, 1428 isCameraRelative, 1429 cameraPositionWS, 1430 viewProjMatrix, 1431 cmd.m_WrappedCommandBuffer, 1432 taaEnabled, hasCloudLayer, cloudOpacityTexture, sunOcclusionTexture, 1433 colorBuffer, 1434 GetLensFlareLightAttenuation, 1435 debugView); 1436 } 1437 1438 /// <summary> 1439 /// Effective Job of drawing the set of Lens Flare registered 1440 /// </summary> 1441 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 1442 /// <param name="cam">Camera</param> 1443 /// <param name="viewport">Viewport used for rendering and XR applied.</param> 1444 /// <param name="xr">XRPass data.</param> 1445 /// <param name="xrIndex">XR multipass ID.</param> 1446 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 1447 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 1448 /// <param name="usePanini">Set if use Panani Projection</param> 1449 /// <param name="paniniDistance">Distance used for Panini projection</param> 1450 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 1451 /// <param name="isCameraRelative">Set if camera is relative</param> 1452 /// <param name="cameraPositionWS">Camera World Space position</param> 1453 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 1454 /// <param name="cmd">Command Buffer</param> 1455 /// <param name="taaEnabled">Set if TAA is enabled</param> 1456 /// <param name="hasCloudLayer">Unused</param> 1457 /// <param name="cloudOpacityTexture">Unused</param> 1458 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 1459 /// <param name="colorBuffer">Source Render Target which contains the Color Buffer</param> 1460 /// <param name="GetLensFlareLightAttenuation">Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP</param> 1461 /// <param name="_FlareOcclusionTex">ShaderID for the FlareOcclusionTex</param> 1462 /// <param name="_FlareOcclusionIndex">ShaderID for the FlareOcclusionIndex</param> 1463 /// <param name="_FlareOcclusionRemapTex">ShaderID for the OcclusionRemap</param> 1464 /// <param name="_FlareCloudOpacity">ShaderID for the FlareCloudOpacity</param> 1465 /// <param name="_FlareSunOcclusionTex">ShaderID for the _FlareSunOcclusionTex</param> 1466 /// <param name="_FlareTex">ShaderID for the FlareTex</param> 1467 /// <param name="_FlareColorValue">ShaderID for the FlareColor</param> 1468 /// <param name="_FlareData0">ShaderID for the FlareData0</param> 1469 /// <param name="_FlareData1">ShaderID for the FlareData1</param> 1470 /// <param name="_FlareData2">ShaderID for the FlareData2</param> 1471 /// <param name="_FlareData3">ShaderID for the FlareData3</param> 1472 /// <param name="_FlareData4">ShaderID for the FlareData4</param> 1473 /// <param name="debugView">Debug View which setup black background to see only Lens Flare</param> 1474 [Obsolete("Use DoLensFlareDataDrivenCommon without _FlareOcclusionRemapTex.._FlareData4 parameters.")] 1475 static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, 1476 float actualWidth, float actualHeight, 1477 bool usePanini, float paniniDistance, float paniniCropToFit, 1478 bool isCameraRelative, 1479 Vector3 cameraPositionWS, 1480 Matrix4x4 viewProjMatrix, 1481 Rendering.CommandBuffer cmd, 1482 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture, 1483 Rendering.RenderTargetIdentifier colorBuffer, 1484 System.Func<Light, Camera, Vector3, float> GetLensFlareLightAttenuation, 1485 int _FlareOcclusionRemapTex, int _FlareOcclusionTex, int _FlareOcclusionIndex, 1486 int _FlareCloudOpacity, int _FlareSunOcclusionTex, 1487 int _FlareTex, int _FlareColorValue, int _FlareData0, int _FlareData1, int _FlareData2, int _FlareData3, int _FlareData4, 1488 bool debugView) 1489 { 1490 DoLensFlareDataDrivenCommon(lensFlareShader, cam, viewport, xr, xrIndex, 1491 actualWidth, actualHeight, 1492 usePanini, paniniDistance, paniniCropToFit, 1493 isCameraRelative, 1494 cameraPositionWS, 1495 viewProjMatrix, 1496 cmd, 1497 taaEnabled, hasCloudLayer, cloudOpacityTexture, sunOcclusionTexture, 1498 colorBuffer, 1499 GetLensFlareLightAttenuation, 1500 debugView); 1501 } 1502 1503 /// <summary> 1504 /// Effective Job of drawing the set of Lens Flare registered 1505 /// </summary> 1506 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 1507 /// <param name="cam">Camera</param> 1508 /// <param name="viewport">Viewport used for rendering and XR applied.</param> 1509 /// <param name="xr">XRPass data.</param> 1510 /// <param name="xrIndex">XR multipass ID.</param> 1511 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 1512 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 1513 /// <param name="usePanini">Set if use Panani Projection</param> 1514 /// <param name="paniniDistance">Distance used for Panini projection</param> 1515 /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> 1516 /// <param name="isCameraRelative">Set if camera is relative</param> 1517 /// <param name="cameraPositionWS">Camera World Space position</param> 1518 /// <param name="viewProjMatrix">View Projection Matrix of the current camera</param> 1519 /// <param name="cmd">Command Buffer</param> 1520 /// <param name="taaEnabled">Set if TAA is enabled</param> 1521 /// <param name="hasCloudLayer">Unused</param> 1522 /// <param name="cloudOpacityTexture">Unused</param> 1523 /// <param name="sunOcclusionTexture">Sun Occlusion Texture from VolumetricCloud on HDRP or null</param> 1524 /// <param name="colorBuffer">Source Render Target which contains the Color Buffer</param> 1525 /// <param name="GetLensFlareLightAttenuation">Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP</param> 1526 /// <param name="debugView">Debug View which setup black background to see only Lens Flare</param> 1527 static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera cam, Rect viewport, XRPass xr, int xrIndex, 1528 float actualWidth, float actualHeight, 1529 bool usePanini, float paniniDistance, float paniniCropToFit, 1530 bool isCameraRelative, 1531 Vector3 cameraPositionWS, 1532 Matrix4x4 viewProjMatrix, 1533 Rendering.CommandBuffer cmd, 1534 bool taaEnabled, bool hasCloudLayer, Texture cloudOpacityTexture, Texture sunOcclusionTexture, 1535 Rendering.RenderTargetIdentifier colorBuffer, 1536 System.Func<Light, Camera, Vector3, float> GetLensFlareLightAttenuation, 1537 bool debugView) 1538 { 1539#if UNITY_EDITOR 1540 bool inPrefabStage = IsPrefabStageEnabled(); 1541 UnityEditor.SceneManagement.PrefabStage prefabStage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage(); 1542 GameObject prefabGameObject = null; 1543 LensFlareComponentSRP[] prefabStageLensFlares = null; 1544 if (prefabStage != null) 1545 { 1546 prefabGameObject = prefabStage.prefabContentsRoot; 1547 if (prefabGameObject == null) 1548 return; 1549 prefabStageLensFlares = GetLensFlareComponents(prefabGameObject); 1550 if (prefabStageLensFlares.Length == 0) 1551 { 1552 return; 1553 } 1554 } 1555#endif 1556 1557 xr.StopSinglePass(cmd); 1558 1559 Vector2 vScreenRatio; 1560 1561 if (Instance.IsEmpty()) 1562 return; 1563 1564#if UNITY_EDITOR 1565 if (cam.cameraType == CameraType.SceneView) 1566 { 1567 // Determine whether the "Animated Materials" checkbox is checked for the current view. 1568 for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++) // Using a foreach on an ArrayList generates garbage ... 1569 { 1570 var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView; 1571 if (sv.camera == cam && !sv.sceneViewState.flaresEnabled) 1572 { 1573 return; 1574 } 1575 } 1576 } 1577#endif 1578 1579 Vector2 screenSize = new Vector2(actualWidth, actualHeight); 1580 float screenRatio = screenSize.x / screenSize.y; 1581 vScreenRatio = new Vector2(screenRatio, 1.0f); 1582 1583#if ENABLE_VR && ENABLE_XR_MODULE 1584 if (xr.enabled && xr.singlePassEnabled) 1585 { 1586 CoreUtils.SetRenderTarget(cmd, colorBuffer, depthSlice: xrIndex); 1587 cmd.SetGlobalInt(_ViewId, xrIndex); 1588 } 1589 else 1590#endif 1591 { 1592 CoreUtils.SetRenderTarget(cmd, colorBuffer); 1593 if (xr.enabled) // multipass 1594 cmd.SetGlobalInt(_ViewId, xr.multipassId); 1595 else 1596 cmd.SetGlobalInt(_ViewId, 0); 1597 } 1598 1599 cmd.SetViewport(viewport); 1600 if (debugView) 1601 { 1602 // Background pitch black to see only the Flares 1603 cmd.ClearRenderTarget(false, true, Color.black); 1604 } 1605 1606 foreach (LensFlareCompInfo info in m_Data) 1607 { 1608 if (info == null || info.comp == null) 1609 continue; 1610 1611 LensFlareComponentSRP comp = info.comp; 1612 LensFlareDataSRP data = comp.lensFlareData; 1613 1614 if (IsLensFlareSRPHidden(cam, comp, data)) 1615 continue; 1616 1617#if UNITY_EDITOR 1618 if (inPrefabStage && !IsCurrentPrefabLensFlareComponent(prefabGameObject, prefabStageLensFlares, comp)) 1619 { 1620 continue; 1621 } 1622#endif 1623 1624 Light light = null; 1625 if (!comp.TryGetComponent<Light>(out light)) 1626 light = null; 1627 1628 Vector3 positionWS; 1629 Vector3 viewportPos; 1630 1631 bool isDirLight = false; 1632 if (light != null && light.type == LightType.Directional) 1633 { 1634 positionWS = -light.transform.forward * cam.farClipPlane; 1635 isDirLight = true; 1636 } 1637 else 1638 { 1639 positionWS = comp.transform.position; 1640 } 1641 1642 // After positionWS computation, lightOverride do not change the position 1643 if (comp.lightOverride != null) 1644 { 1645 light = comp.lightOverride; 1646 } 1647 1648 viewportPos = WorldToViewport(cam, !isDirLight, isCameraRelative, viewProjMatrix, positionWS); 1649 1650 if (usePanini && cam == Camera.main) 1651 { 1652 viewportPos = DoPaniniProjection(viewportPos, actualWidth, actualHeight, cam.fieldOfView, paniniCropToFit, paniniDistance); 1653 } 1654 1655 if (viewportPos.z < 0.0f) 1656 continue; 1657 1658 if (!comp.allowOffScreen) 1659 { 1660 if (viewportPos.x < 0.0f || viewportPos.x > 1.0f || 1661 viewportPos.y < 0.0f || viewportPos.y > 1.0f) 1662 continue; 1663 } 1664 1665 Vector3 diffToObject = positionWS - cameraPositionWS; 1666 // Check if the light is forward, can be an issue with, 1667 // the math associated to Panini projection 1668 if (Vector3.Dot(cam.transform.forward, diffToObject) < 0.0f) 1669 { 1670 continue; 1671 } 1672 float distToObject = diffToObject.magnitude; 1673 float coefDistSample = distToObject / comp.maxAttenuationDistance; 1674 float coefScaleSample = distToObject / comp.maxAttenuationScale; 1675 float distanceAttenuation = !isDirLight && comp.distanceAttenuationCurve.length > 0 ? comp.distanceAttenuationCurve.Evaluate(coefDistSample) : 1.0f; 1676 float scaleByDistance = !isDirLight && comp.scaleByDistanceCurve.length >= 1 ? comp.scaleByDistanceCurve.Evaluate(coefScaleSample) : 1.0f; 1677 1678 Color globalColorModulation = Color.white; 1679 1680 if (light != null) 1681 { 1682 if (comp.attenuationByLightShape) 1683 globalColorModulation *= GetLensFlareLightAttenuation(light, cam, -diffToObject.normalized); 1684 } 1685 1686 Vector2 screenPos = new Vector2(2.0f * viewportPos.x - 1.0f, -(2.0f * viewportPos.y - 1.0f)); 1687 1688 if(!SystemInfo.graphicsUVStartsAtTop && isDirLight) // Y-flip for OpenGL & directional light 1689 screenPos.y = -screenPos.y; 1690 1691 Vector2 radPos = new Vector2(Mathf.Abs(screenPos.x), Mathf.Abs(screenPos.y)); 1692 float radius = Mathf.Max(radPos.x, radPos.y); // l1 norm (instead of l2 norm) 1693 float radialsScaleRadius = comp.radialScreenAttenuationCurve.length > 0 ? comp.radialScreenAttenuationCurve.Evaluate(radius) : 1.0f; 1694 1695 float compIntensity = comp.intensity * radialsScaleRadius * distanceAttenuation; 1696 1697 if (compIntensity <= 0.0f) 1698 continue; 1699 1700 globalColorModulation *= distanceAttenuation; 1701 1702 Vector3 dir = (cam.transform.position - comp.transform.position).normalized; 1703 Vector3 screenPosZ = WorldToViewport(cam, !isDirLight, isCameraRelative, viewProjMatrix, positionWS + dir * comp.occlusionOffset); 1704 1705 float adjustedOcclusionRadius = isDirLight ? comp.celestialProjectedOcclusionRadius(cam) : comp.occlusionRadius; 1706 Vector2 occlusionRadiusEdgeScreenPos0 = (Vector2)viewportPos; 1707 Vector2 occlusionRadiusEdgeScreenPos1 = (Vector2)WorldToViewport(cam, !isDirLight, isCameraRelative, viewProjMatrix, positionWS + cam.transform.up * adjustedOcclusionRadius); 1708 float occlusionRadius = (occlusionRadiusEdgeScreenPos1 - occlusionRadiusEdgeScreenPos0).magnitude; 1709 1710 if (comp.useOcclusion) 1711 { 1712 cmd.SetGlobalTexture(_FlareOcclusionTex, occlusionRT); 1713 cmd.EnableShaderKeyword("FLARE_HAS_OCCLUSION"); 1714 } 1715 else 1716 { 1717 cmd.DisableShaderKeyword("FLARE_HAS_OCCLUSION"); 1718 } 1719 1720 if (IsOcclusionRTCompatible()) 1721 { 1722 cmd.DisableShaderKeyword("FLARE_OPENGL3_OR_OPENGLCORE"); 1723 } 1724 else 1725 { 1726 cmd.EnableShaderKeyword("FLARE_OPENGL3_OR_OPENGLCORE"); 1727 } 1728 1729 cmd.SetGlobalVector(_FlareOcclusionIndex, new Vector4((float)info.index, 0.0f, 0.0f, 0.0f)); 1730 cmd.SetGlobalTexture(_FlareOcclusionRemapTex, comp.occlusionRemapCurve.GetTexture()); 1731 1732 Vector4 flareData1 = new Vector4(0.0f, comp.sampleCount, screenPosZ.z, actualHeight / actualWidth); 1733 ProcessLensFlareSRPElements(ref data.elements, cmd, globalColorModulation, light, 1734 compIntensity, scaleByDistance * comp.scale, lensFlareShader, 1735 screenPos, comp.allowOffScreen, vScreenRatio, flareData1, false, 0); 1736 } 1737 1738 xr.StartSinglePass(cmd); 1739 } 1740 1741 /// <summary> 1742 /// Effective Job of drawing Lens Flare Screen Space. 1743 /// </summary> 1744 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 1745 /// <param name="cam">Camera</param> 1746 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 1747 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 1748 /// <param name="tintColor">tintColor to multiply all the flare by</param> 1749 /// <param name="originalBloomTexture">original Bloom texture used to write on at the end of compositing</param> 1750 /// <param name="bloomMipTexture">Bloom mip texture used as data for the effect</param> 1751 /// <param name="spectralLut">spectralLut used for chromatic aberration effect</param> 1752 /// <param name="streakTextureTmp">Texture used for the multiple pass streaks effect</param> 1753 /// <param name="streakTextureTmp2">Texture used for the multiple pass streaks effect</param> 1754 /// <param name="parameters1">globalIntensity, regularIntensity, reverseIntensity, warpedIntensity</param> 1755 /// <param name="parameters2">vignetteEffect, startingPosition, scale, freeSlot</param> 1756 /// <param name="parameters3">samples, sampleDimmer, chromaticAbberationIntensity, chromaticAbberationSamples</param> 1757 /// <param name="parameters4">streaksIntensity, streaksLength, streaksOrientation, streaksThreshold</param> 1758 /// <param name="parameters5">downsampleStreak, warpedFlareScaleX, warpedFlareScaleY, freeSlot</param> 1759 /// <param name="cmd">UnsafeCommandBuffer</param> 1760 /// <param name="result">Result RT for the Lens Flare Screen Space</param> 1761 /// <param name="debugView">Information if we are in debug mode or not</param> 1762 static public void DoLensFlareScreenSpaceCommon( 1763 Material lensFlareShader, 1764 Camera cam, 1765 float actualWidth, 1766 float actualHeight, 1767 Color tintColor, 1768 Texture originalBloomTexture, 1769 Texture bloomMipTexture, 1770 Texture spectralLut, 1771 Texture streakTextureTmp, 1772 Texture streakTextureTmp2, 1773 Vector4 parameters1, 1774 Vector4 parameters2, 1775 Vector4 parameters3, 1776 Vector4 parameters4, 1777 Vector4 parameters5, 1778 UnsafeCommandBuffer cmd, 1779 RTHandle result, 1780 bool debugView) 1781 { 1782 DoLensFlareScreenSpaceCommon( 1783 lensFlareShader, 1784 cam, 1785 actualWidth, 1786 actualHeight, 1787 tintColor, 1788 originalBloomTexture, 1789 bloomMipTexture, 1790 spectralLut, 1791 streakTextureTmp, 1792 streakTextureTmp2, 1793 parameters1, 1794 parameters2, 1795 parameters3, 1796 parameters4, 1797 parameters5, 1798 cmd.m_WrappedCommandBuffer, 1799 result, 1800 debugView); 1801 } 1802 1803 /// <summary> 1804 /// Effective Job of drawing Lens Flare Screen Space. 1805 /// </summary> 1806 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 1807 /// <param name="cam">Camera</param> 1808 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 1809 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 1810 /// <param name="tintColor">tintColor to multiply all the flare by</param> 1811 /// <param name="originalBloomTexture">original Bloom texture used to write on at the end of compositing</param> 1812 /// <param name="bloomMipTexture">Bloom mip texture used as data for the effect</param> 1813 /// <param name="spectralLut">spectralLut used for chromatic aberration effect</param> 1814 /// <param name="streakTextureTmp">Texture used for the multiple pass streaks effect</param> 1815 /// <param name="streakTextureTmp2">Texture used for the multiple pass streaks effect</param> 1816 /// <param name="parameters1">globalIntensity, regularIntensity, reverseIntensity, warpedIntensity</param> 1817 /// <param name="parameters2">vignetteEffect, startingPosition, scale, freeSlot</param> 1818 /// <param name="parameters3">samples, sampleDimmer, chromaticAbberationIntensity, chromaticAbberationSamples</param> 1819 /// <param name="parameters4">streaksIntensity, streaksLength, streaksOrientation, streaksThreshold</param> 1820 /// <param name="parameters5">downsampleStreak, warpedFlareScaleX, warpedFlareScaleY, freeSlot</param> 1821 /// <param name="cmd">Command Buffer</param> 1822 /// <param name="result">Result RT for the Lens Flare Screen Space</param> 1823 /// <param name="_LensFlareScreenSpaceBloomMipTexture">ShaderID for the original bloom texture</param> 1824 /// <param name="_LensFlareScreenSpaceResultTexture">ShaderID for the LensFlareScreenSpaceResultTexture texture</param> 1825 /// <param name="_LensFlareScreenSpaceSpectralLut">ShaderID for the LensFlareScreenSpaceSpectralLut texture</param> 1826 /// <param name="_LensFlareScreenSpaceStreakTex">ShaderID for the LensFlareScreenSpaceStreakTex streak temp texture</param> 1827 /// <param name="_LensFlareScreenSpaceMipLevel">ShaderID for the LensFlareScreenSpaceMipLevel parameter</param> 1828 /// <param name="_LensFlareScreenSpaceTintColor">ShaderID for the LensFlareScreenSpaceTintColor color</param> 1829 /// <param name="_LensFlareScreenSpaceParams1">ShaderID for the LensFlareScreenSpaceParams1</param> 1830 /// <param name="_LensFlareScreenSpaceParams2">ShaderID for the LensFlareScreenSpaceParams2</param> 1831 /// <param name="_LensFlareScreenSpaceParams3">ShaderID for the LensFlareScreenSpaceParams3</param> 1832 /// <param name="_LensFlareScreenSpaceParams4">ShaderID for the LensFlareScreenSpaceParams4</param> 1833 /// <param name="_LensFlareScreenSpaceParams5">ShaderID for the LensFlareScreenSpaceParams5</param> 1834 /// <param name="debugView">Information if we are in debug mode or not</param> 1835 [Obsolete("Use DoLensFlareScreenSpaceCommon without _Shader IDs parameters.")] 1836 static public void DoLensFlareScreenSpaceCommon( 1837 Material lensFlareShader, 1838 Camera cam, 1839 float actualWidth, 1840 float actualHeight, 1841 Color tintColor, 1842 Texture originalBloomTexture, 1843 Texture bloomMipTexture, 1844 Texture spectralLut, 1845 Texture streakTextureTmp, 1846 Texture streakTextureTmp2, 1847 Vector4 parameters1, 1848 Vector4 parameters2, 1849 Vector4 parameters3, 1850 Vector4 parameters4, 1851 Vector4 parameters5, 1852 Rendering.CommandBuffer cmd, 1853 RTHandle result, 1854 int _LensFlareScreenSpaceBloomMipTexture, 1855 int _LensFlareScreenSpaceResultTexture, 1856 int _LensFlareScreenSpaceSpectralLut, 1857 int _LensFlareScreenSpaceStreakTex, 1858 int _LensFlareScreenSpaceMipLevel, 1859 int _LensFlareScreenSpaceTintColor, 1860 int _LensFlareScreenSpaceParams1, 1861 int _LensFlareScreenSpaceParams2, 1862 int _LensFlareScreenSpaceParams3, 1863 int _LensFlareScreenSpaceParams4, 1864 int _LensFlareScreenSpaceParams5, 1865 bool debugView) 1866 { 1867 DoLensFlareScreenSpaceCommon( 1868 lensFlareShader, 1869 cam, 1870 actualWidth, 1871 actualHeight, 1872 tintColor, 1873 originalBloomTexture, 1874 bloomMipTexture, 1875 spectralLut, 1876 streakTextureTmp, 1877 streakTextureTmp2, 1878 parameters1, 1879 parameters2, 1880 parameters3, 1881 parameters4, 1882 parameters5, 1883 cmd, 1884 result, 1885 debugView); 1886 } 1887 1888 /// <summary> 1889 /// Effective Job of drawing Lens Flare Screen Space. 1890 /// </summary> 1891 /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> 1892 /// <param name="cam">Camera</param> 1893 /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> 1894 /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> 1895 /// <param name="tintColor">tintColor to multiply all the flare by</param> 1896 /// <param name="originalBloomTexture">original Bloom texture used to write on at the end of compositing</param> 1897 /// <param name="bloomMipTexture">Bloom mip texture used as data for the effect</param> 1898 /// <param name="spectralLut">spectralLut used for chromatic aberration effect</param> 1899 /// <param name="streakTextureTmp">Texture used for the multiple pass streaks effect</param> 1900 /// <param name="streakTextureTmp2">Texture used for the multiple pass streaks effect</param> 1901 /// <param name="parameters1">globalIntensity, regularIntensity, reverseIntensity, warpedIntensity</param> 1902 /// <param name="parameters2">vignetteEffect, startingPosition, scale, freeSlot</param> 1903 /// <param name="parameters3">samples, sampleDimmer, chromaticAbberationIntensity, chromaticAbberationSamples</param> 1904 /// <param name="parameters4">streaksIntensity, streaksLength, streaksOrientation, streaksThreshold</param> 1905 /// <param name="parameters5">downsampleStreak, warpedFlareScaleX, warpedFlareScaleY, freeSlot</param> 1906 /// <param name="cmd">Command Buffer</param> 1907 /// <param name="result">Result RT for the Lens Flare Screen Space</param> 1908 /// <param name="debugView">Information if we are in debug mode or not</param> 1909 static public void DoLensFlareScreenSpaceCommon( 1910 Material lensFlareShader, 1911 Camera cam, 1912 float actualWidth, 1913 float actualHeight, 1914 Color tintColor, 1915 Texture originalBloomTexture, 1916 Texture bloomMipTexture, 1917 Texture spectralLut, 1918 Texture streakTextureTmp, 1919 Texture streakTextureTmp2, 1920 Vector4 parameters1, 1921 Vector4 parameters2, 1922 Vector4 parameters3, 1923 Vector4 parameters4, 1924 Vector4 parameters5, 1925 Rendering.CommandBuffer cmd, 1926 RTHandle result, 1927 bool debugView) 1928 { 1929 1930 //Multiplying parameters value here for easier maintenance since they are the same numbers between SRPs 1931 parameters2.x = Mathf.Pow(parameters2.x, 0.25f); // Vignette effect 1932 parameters3.z = parameters3.z / 20f; // chromaticAbberationIntensity 1933 parameters4.y = parameters4.y * 10f; // Streak Length 1934 parameters4.z = parameters4.z / 90f; // Streak Orientation 1935 parameters5.y = 1.0f / parameters5.y; // WarpedFlareScale X 1936 parameters5.z = 1.0f / parameters5.z; // WarpedFlareScale Y 1937 1938 cmd.SetViewport(new Rect() { width = actualWidth, height = actualHeight }); 1939 if (debugView) 1940 { 1941 // Background pitch black to see only the flares 1942 cmd.ClearRenderTarget(false, true, Color.black); 1943 } 1944 1945#if UNITY_EDITOR 1946 if (cam.cameraType == CameraType.SceneView) 1947 { 1948 // Determine whether the "Flare" checkbox is checked for the current view. 1949 for (int i = 0; i < UnityEditor.SceneView.sceneViews.Count; i++) // Using a foreach on an ArrayList generates garbage ... 1950 { 1951 var sv = UnityEditor.SceneView.sceneViews[i] as UnityEditor.SceneView; 1952 if (sv.camera == cam && !sv.sceneViewState.flaresEnabled) 1953 { 1954 return; 1955 } 1956 } 1957 } 1958#endif 1959 1960 // Multiple scaleX by aspect ratio so that default 1:1 scale for warped flare stays circular (as in data driven lens flare) 1961 float warpedScaleX = parameters5.y; 1962 warpedScaleX *= actualWidth / actualHeight; 1963 parameters5.y = warpedScaleX; 1964 1965 // This is to make sure the streak length is the same in all resolutions 1966 float streaksLength = parameters4.y; 1967 streaksLength *= actualWidth * 0.0005f; 1968 parameters4.y = streaksLength; 1969 1970 // List of the passes in LensFlareScreenSpace.shader 1971 int prefilterPass = lensFlareShader.FindPass("LensFlareScreenSpac Prefilter"); 1972 int downSamplePass = lensFlareShader.FindPass("LensFlareScreenSpace Downsample"); 1973 int upSamplePass = lensFlareShader.FindPass("LensFlareScreenSpace Upsample"); 1974 int compositionPass = lensFlareShader.FindPass("LensFlareScreenSpace Composition"); 1975 int writeToBloomPass = lensFlareShader.FindPass("LensFlareScreenSpace Write to BloomTexture"); 1976 1977 // Setting the input textures 1978 cmd.SetGlobalTexture(_LensFlareScreenSpaceBloomMipTexture, bloomMipTexture); 1979 cmd.SetGlobalTexture(_LensFlareScreenSpaceSpectralLut, spectralLut); 1980 1981 // Setting parameters of the effects 1982 cmd.SetGlobalVector(_LensFlareScreenSpaceParams1, parameters1); 1983 cmd.SetGlobalVector(_LensFlareScreenSpaceParams2, parameters2); 1984 cmd.SetGlobalVector(_LensFlareScreenSpaceParams3, parameters3); 1985 cmd.SetGlobalVector(_LensFlareScreenSpaceParams4, parameters4); 1986 cmd.SetGlobalVector(_LensFlareScreenSpaceParams5, parameters5); 1987 cmd.SetGlobalColor(_LensFlareScreenSpaceTintColor, tintColor); 1988 1989 // We only do the first 3 pass if StreakIntensity (parameters4.x) is set to something above 0 to save costs 1990 if (parameters4.x > 0) 1991 { 1992 // Prefilter 1993 Rendering.CoreUtils.SetRenderTarget(cmd, streakTextureTmp); 1994 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, prefilterPass); 1995 1996 int maxLevel = Mathf.FloorToInt(Mathf.Log(Mathf.Max(actualHeight, actualWidth), 2.0f)); 1997 int maxLevelDownsample = Mathf.Max(1, maxLevel); 1998 int maxLevelUpsample = 2; 1999 int startIndex = 0; 2000 bool even = false; 2001 2002 // Downsample 2003 for (int i = 0; i < maxLevelDownsample; i++) 2004 { 2005 even = (i % 2 == 0); 2006 cmd.SetGlobalInt(_LensFlareScreenSpaceMipLevel, i); 2007 cmd.SetGlobalTexture(_LensFlareScreenSpaceStreakTex, even ? streakTextureTmp : streakTextureTmp2); 2008 Rendering.CoreUtils.SetRenderTarget(cmd, even ? streakTextureTmp2 : streakTextureTmp); 2009 2010 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, downSamplePass); 2011 } 2012 2013 //Since we do a ping pong between streakTextureTmp & streakTextureTmp2, we need to know which texture is the last; 2014 if (even) 2015 startIndex = 1; 2016 2017 //Upsample 2018 for (int i = startIndex; i < (startIndex + maxLevelUpsample); i++) 2019 { 2020 even = (i % 2 == 0); 2021 cmd.SetGlobalInt(_LensFlareScreenSpaceMipLevel, (i - startIndex)); 2022 cmd.SetGlobalTexture(_LensFlareScreenSpaceStreakTex, even ? streakTextureTmp : streakTextureTmp2); 2023 Rendering.CoreUtils.SetRenderTarget(cmd, even ? streakTextureTmp2 : streakTextureTmp); 2024 2025 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, upSamplePass); 2026 } 2027 2028 cmd.SetGlobalTexture(_LensFlareScreenSpaceStreakTex, even ? streakTextureTmp2 : streakTextureTmp); 2029 } 2030 2031 // Composition (Flares + Streaks) 2032 Rendering.CoreUtils.SetRenderTarget(cmd, result); 2033 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, compositionPass); 2034 2035 // Final pass, we add the result of the previous pass to the Original Bloom Texture. 2036 cmd.SetGlobalTexture(_LensFlareScreenSpaceResultTexture, result); 2037 Rendering.CoreUtils.SetRenderTarget(cmd, originalBloomTexture); 2038 UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, writeToBloomPass); 2039 } 2040 2041#region Panini Projection 2042 static Vector2 DoPaniniProjection(Vector2 screenPos, float actualWidth, float actualHeight, float fieldOfView, float paniniProjectionCropToFit, float paniniProjectionDistance) 2043 { 2044 Vector2 viewExtents = CalcViewExtents(actualWidth, actualHeight, fieldOfView); 2045 Vector2 cropExtents = CalcCropExtents(actualWidth, actualHeight, fieldOfView, paniniProjectionDistance); 2046 2047 float scaleX = cropExtents.x / viewExtents.x; 2048 float scaleY = cropExtents.y / viewExtents.y; 2049 float scaleF = Mathf.Min(scaleX, scaleY); 2050 2051 float paniniD = paniniProjectionDistance; 2052 float paniniS = Mathf.Lerp(1.0f, Mathf.Clamp01(scaleF), paniniProjectionCropToFit); 2053 2054 Vector2 pos = new Vector2(2.0f * screenPos.x - 1.0f, 2.0f * screenPos.y - 1.0f); 2055 2056 Vector2 projPos = Panini_Generic_Inv(pos * viewExtents, paniniD) / (viewExtents * paniniS); 2057 2058 return new Vector2(0.5f * projPos.x + 0.5f, 0.5f * projPos.y + 0.5f); 2059 } 2060 2061 static Vector2 CalcViewExtents(float actualWidth, float actualHeight, float fieldOfView) 2062 { 2063 float fovY = fieldOfView * Mathf.Deg2Rad; 2064 float aspect = actualWidth / actualHeight; 2065 2066 float viewExtY = Mathf.Tan(0.5f * fovY); 2067 float viewExtX = aspect * viewExtY; 2068 2069 return new Vector2(viewExtX, viewExtY); 2070 } 2071 2072 static Vector2 CalcCropExtents(float actualWidth, float actualHeight, float fieldOfView, float d) 2073 { 2074 // given 2075 // S----------- E--X------- 2076 // | ` ~. /,´ 2077 // |-- --- Q 2078 // | ,/ ` 2079 // 1 | ,´/ ` 2080 // | ,´ / ´ 2081 // | ,´ / ´ 2082 // |,` / , 2083 // O / 2084 // | / , 2085 // d | / 2086 // | / , 2087 // |/ . 2088 // P 2089 // | ´ 2090 // | , ´ 2091 // +- ´ 2092 // 2093 // have X 2094 // want to find E 2095 2096 float viewDist = 1.0f + d; 2097 2098 Vector2 projPos = CalcViewExtents(actualWidth, actualHeight, fieldOfView); 2099 float projHyp = Mathf.Sqrt(projPos.x * projPos.x + 1.0f); 2100 2101 float cylDistMinusD = 1.0f / projHyp; 2102 float cylDist = cylDistMinusD + d; 2103 Vector2 cylPos = projPos * cylDistMinusD; 2104 2105 return cylPos * (viewDist / cylDist); 2106 } 2107 2108 static Vector2 Panini_Generic_Inv(Vector2 projPos, float d) 2109 { 2110 // given 2111 // S----------- E--X------- 2112 // | ` ~. /,´ 2113 // |-- --- Q 2114 // | ,/ ` 2115 // 1 | ,´/ ` 2116 // | ,´ / ´ 2117 // | ,´ / ´ 2118 // |,` / , 2119 // O / 2120 // | / , 2121 // d | / 2122 // | / , 2123 // |/ . 2124 // P 2125 // | ´ 2126 // | , ´ 2127 // +- ´ 2128 // 2129 // have X 2130 // want to find E 2131 2132 float viewDist = 1.0f + d; 2133 float projHyp = Mathf.Sqrt(projPos.x * projPos.x + 1.0f); 2134 2135 float cylDistMinusD = 1.0f / projHyp; 2136 float cylDist = cylDistMinusD + d; 2137 Vector2 cylPos = projPos * cylDistMinusD; 2138 2139 return cylPos * (viewDist / cylDist); 2140 } 2141 2142#endregion 2143 } 2144}