Skip to content

Commit 03116fa

Browse files
alelievrEvergreen
authored andcommitted
Fix fog scattering in HDRP
Fix fog scattering in HDRP that didn't account for opaque objects' color. https://media.github.cds.internal.unity3d.com/user/745/files/639309be-e188-4586-896a-cdcb481e45a6
1 parent fec3d38 commit 03116fa

29 files changed

+2038
-156
lines changed

Packages/com.unity.render-pipelines.core/Editor/PostProcessing/LensFlareComponentSRPEditor.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@ class LensFlareComponentSRPEditor : Editor
2222
SerializedProperty m_AttenuationByLightShape;
2323
SerializedProperty m_RadialScreenAttenuationCurve;
2424
SerializedProperty m_UseOcclusion;
25-
SerializedProperty m_BackgroundCloudOcclusion;
25+
SerializedProperty m_fogOcclusion;
2626
SerializedProperty m_WaterOcclusion;
2727
SerializedProperty m_OcclusionRadius;
2828
SerializedProperty m_SamplesCount;
2929
SerializedProperty m_OcclusionOffset;
3030
SerializedProperty m_AllowOffScreen;
31-
SerializedProperty m_VolumetricCloudOcclusion;
3231
SerializedProperty m_OcclusionRemapTextureCurve;
3332
SerializedProperty m_OcclusionRemapCurve;
3433
SerializedProperty m_LightOverride;
3534

35+
Light m_AttachedLight;
36+
3637
void MakeTextureDirtyCallback()
3738
{
3839
LensFlareComponentSRP comp = target as LensFlareComponentSRP;
@@ -41,6 +42,10 @@ void MakeTextureDirtyCallback()
4142

4243
void OnEnable()
4344
{
45+
if (targets.Length == 1)
46+
m_AttachedLight = (target as Component)?.GetComponent<Light>();
47+
else
48+
m_AttachedLight = null;
4449
PropertyFetcher<LensFlareComponentSRP> entryPoint = new PropertyFetcher<LensFlareComponentSRP>(serializedObject);
4550
m_LensFlareData = entryPoint.Find("m_LensFlareData");
4651
m_Intensity = entryPoint.Find(x => x.intensity);
@@ -52,13 +57,12 @@ void OnEnable()
5257
m_AttenuationByLightShape = entryPoint.Find(x => x.attenuationByLightShape);
5358
m_RadialScreenAttenuationCurve = entryPoint.Find(x => x.radialScreenAttenuationCurve);
5459
m_UseOcclusion = entryPoint.Find(x => x.useOcclusion);
55-
m_BackgroundCloudOcclusion = entryPoint.Find(x => x.useBackgroundCloudOcclusion);
60+
m_fogOcclusion = entryPoint.Find(x => x.useFogOpacityOcclusion);
5661
m_WaterOcclusion = entryPoint.Find(x => x.useWaterOcclusion);
5762
m_OcclusionRadius = entryPoint.Find(x => x.occlusionRadius);
5863
m_SamplesCount = entryPoint.Find(x => x.sampleCount);
5964
m_OcclusionOffset = entryPoint.Find(x => x.occlusionOffset);
6065
m_AllowOffScreen = entryPoint.Find(x => x.allowOffScreen);
61-
m_VolumetricCloudOcclusion = entryPoint.Find(x => x.volumetricCloudOcclusion);
6266
m_OcclusionRemapTextureCurve = entryPoint.Find(x => x.occlusionRemapCurve);
6367
m_OcclusionRemapCurve = m_OcclusionRemapTextureCurve.FindPropertyRelative("m_Curve");
6468
m_LightOverride = entryPoint.Find(x => x.lightOverride);
@@ -156,12 +160,16 @@ public override void OnInspectorGUI()
156160
if (m_UseOcclusion.boolValue)
157161
{
158162
++EditorGUI.indentLevel;
159-
if (RenderPipelineManager.currentPipeline is ICloudBackground)
160-
EditorGUILayout.PropertyField(m_BackgroundCloudOcclusion, Styles.backgroundCloudOcclusion);
161-
if (RenderPipelineManager.currentPipeline is IVolumetricCloud volumetricCloud && volumetricCloud.IsVolumetricCloudUsable())
162-
EditorGUILayout.PropertyField(m_VolumetricCloudOcclusion, Styles.volumetricCloudOcclusion);
163-
if (RenderPipelineManager.currentPipeline is IWaterRendering waterRendering && waterRendering.IsWaterRenderingUsable())
164-
EditorGUILayout.PropertyField(m_WaterOcclusion, Styles.waterOcclusion);
163+
EditorGUI.BeginDisabledGroup(m_AttachedLight != null && m_AttachedLight.type != LightType.Directional);
164+
{
165+
if (RenderPipelineManager.currentPipeline is ICloudBackground)
166+
EditorGUILayout.PropertyField(m_fogOcclusion, Styles.fogAndCloudOpacityOcclusion);
167+
if (RenderPipelineManager.currentPipeline is IWaterRendering waterRendering &&
168+
waterRendering.IsWaterRenderingUsable())
169+
EditorGUILayout.PropertyField(m_WaterOcclusion, Styles.waterOcclusion);
170+
}
171+
EditorGUI.EndDisabledGroup();
172+
165173
EditorGUILayout.PropertyField(m_OcclusionRadius, Styles.occlusionRadius);
166174
EditorGUILayout.PropertyField(m_SamplesCount, Styles.sampleCount);
167175
EditorGUILayout.PropertyField(m_OcclusionOffset, Styles.occlusionOffset);
@@ -199,7 +207,7 @@ static class Styles
199207
static public readonly GUIContent attenuationByLightShape = EditorGUIUtility.TrTextContent("Attenuation By Light Shape", "When enabled, if the component is attached to a light, automatically reduces the effect of the lens flare based on the type and shape of the light.");
200208
static public readonly GUIContent radialScreenAttenuationCurve = EditorGUIUtility.TrTextContent("Screen Attenuation Curve", "Specifies the curve that modifies the intensity of the lens flare based on its distance from the edge of the screen.");
201209
static public readonly GUIContent enableOcclusion = EditorGUIUtility.TrTextContent("Enable", "When enabled, the renderer uses the depth buffer to occlude (partially or completely) the lens flare. Partial occlusion also occurs when the lens flare is partially offscreen.");
202-
static public readonly GUIContent backgroundCloudOcclusion = EditorGUIUtility.TrTextContent("Background Clouds", "When enabled, the occlusion is attenuated by the Background Clouds used on the Visual Environnement (Cloud layer).");
210+
static public readonly GUIContent fogAndCloudOpacityOcclusion = EditorGUIUtility.TrTextContent("Fog And Cloud Opacity", "When enabled, the occlusion is attenuated by the Background Clouds, Volumetric Clouds and the Fog.");
203211
static public readonly GUIContent occlusionRadius = EditorGUIUtility.TrTextContent("Occlusion Radius", "Sets the radius, in meters, around the light used to compute the occlusion of the lens flare. If this area is half occluded by geometry (or half off-screen), the intensity of the lens flare is cut by half.");
204212
static public readonly GUIContent sampleCount = EditorGUIUtility.TrTextContent("Sample Count", "Sets the number of random samples used inside the Occlusion Radius area. A higher sample count gives a smoother attenuation when occluded.");
205213
static public readonly GUIContent occlusionOffset = EditorGUIUtility.TrTextContent("Occlusion Offset", "Sets the offset of the occlusion area in meters between the GameObject this asset is attached to, and the Camera. A positive value moves the occlusion area closer to the Camera.");

Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareCommonSRP.cs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -557,28 +557,22 @@ static public bool IsCloudLayerOpacityNeeded(Camera cam)
557557
(comp.useOcclusion && comp.sampleCount == 0))
558558
continue;
559559

560-
if (comp.useBackgroundCloudOcclusion)
560+
if (comp.useFogOpacityOcclusion)
561561
return true;
562562
}
563563

564564
return false;
565565
}
566566

567-
static void SetOcclusionPermutation(Rendering.CommandBuffer cmd,
568-
bool useBackgroundCloudOcclusion, bool volumetricCloudOcclusion, bool waterOcclusion,
569-
int _FlareCloudOpacity, int _FlareSunOcclusionTex,
570-
Texture cloudOpacityTexture, Texture sunOcclusionTexture, Texture waterGBuffer3Thickness)
567+
static void SetOcclusionPermutation(CommandBuffer cmd,
568+
bool useFogOpacityOcclusion, bool waterOcclusion, int _FlareSunOcclusionTex,
569+
Texture sunOcclusionTexture, Texture waterGBuffer3Thickness)
571570
{
572571
uint occlusionPermutation = (uint)(LensFlareOcclusionPermutation.Depth);
573-
if (useBackgroundCloudOcclusion && cloudOpacityTexture != null)
574-
{
575-
occlusionPermutation |= (uint)(LensFlareOcclusionPermutation.CloudLayer);
576-
cmd.SetGlobalTexture(_FlareCloudOpacity, cloudOpacityTexture);
577-
}
578572

579-
if (volumetricCloudOcclusion && sunOcclusionTexture != null)
573+
if (useFogOpacityOcclusion && sunOcclusionTexture != null)
580574
{
581-
occlusionPermutation |= (uint)(LensFlareOcclusionPermutation.VolumetricCloud);
575+
occlusionPermutation |= (uint)(LensFlareOcclusionPermutation.FogOpacity);
582576
cmd.SetGlobalTexture(_FlareSunOcclusionTex, sunOcclusionTexture);
583577
}
584578

@@ -947,10 +941,8 @@ static public void ComputeOcclusion(Material lensFlareShader, Camera cam, XRPass
947941

948942
cmd.SetGlobalVector(_FlareData1, new Vector4(occlusionRadius, comp.sampleCount, screenPosZ.z, actualHeight / actualWidth));
949943

950-
SetOcclusionPermutation(cmd,
951-
comp.useBackgroundCloudOcclusion && hasCloudLayer, comp.volumetricCloudOcclusion, comp.useWaterOcclusion,
952-
_FlareCloudOpacity, _FlareSunOcclusionTex,
953-
cloudOpacityTexture, sunOcclusionTexture, waterGBuffer3Thickness);
944+
SetOcclusionPermutation(cmd, comp.useFogOpacityOcclusion, comp.useWaterOcclusion,
945+
_FlareSunOcclusionTex, sunOcclusionTexture, waterGBuffer3Thickness);
954946
cmd.EnableShaderKeyword("FLARE_COMPUTE_OCCLUSION");
955947

956948
Vector2 screenPos = new Vector2(2.0f * viewportPos.x - 1.0f, -(2.0f * viewportPos.y - 1.0f));
@@ -1716,7 +1708,7 @@ static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, Camera
17161708

17171709
if(!SystemInfo.graphicsUVStartsAtTop && isDirLight) // Y-flip for OpenGL & directional light
17181710
screenPos.y = -screenPos.y;
1719-
1711+
17201712
Vector2 radPos = new Vector2(Mathf.Abs(screenPos.x), Mathf.Abs(screenPos.y));
17211713
float radius = Mathf.Max(radPos.x, radPos.y); // l1 norm (instead of l2 norm)
17221714
float radialsScaleRadius = comp.radialScreenAttenuationCurve.length > 0 ? comp.radialScreenAttenuationCurve.Evaluate(radius) : 1.0f;
@@ -1955,15 +1947,15 @@ static public void DoLensFlareScreenSpaceCommon(
19551947
RTHandle result,
19561948
bool debugView)
19571949
{
1958-
1959-
//Multiplying parameters value here for easier maintenance since they are the same numbers between SRPs
1950+
1951+
//Multiplying parameters value here for easier maintenance since they are the same numbers between SRPs
19601952
parameters2.x = Mathf.Pow(parameters2.x, 0.25f); // Vignette effect
19611953
parameters3.z = parameters3.z / 20f; // chromaticAbberationIntensity
1962-
parameters4.y = parameters4.y * 10f; // Streak Length
1954+
parameters4.y = parameters4.y * 10f; // Streak Length
19631955
parameters4.z = parameters4.z / 90f; // Streak Orientation
19641956
parameters5.y = 1.0f / parameters5.y; // WarpedFlareScale X
19651957
parameters5.z = 1.0f / parameters5.z; // WarpedFlareScale Y
1966-
1958+
19671959
cmd.SetViewport(new Rect() { width = actualWidth, height = actualHeight });
19681960
if (debugView)
19691961
{

Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareComponentSRP.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Dynamic;
7+
using UnityEngine.Serialization;
78

89
namespace UnityEngine.Rendering
910
{
@@ -17,6 +18,16 @@ public sealed class LensFlareComponentSRP : MonoBehaviour
1718
[SerializeField]
1819
private LensFlareDataSRP m_LensFlareData = null;
1920

21+
enum Version
22+
{
23+
Initial,
24+
}
25+
26+
#pragma warning disable 414
27+
[SerializeField]
28+
Version version = Version.Initial;
29+
#pragma warning restore 414
30+
2031
/// <summary>
2132
/// Lens flare asset used on this component
2233
/// </summary>
@@ -71,8 +82,14 @@ public LensFlareDataSRP lensFlareData
7182
public bool useOcclusion = false;
7283
/// <summary>
7384
/// Enable Occlusion using Background Cloud (for instance: CloudLayer)
85+
/// Please use useFogOpacityOcclusion instead.
7486
/// </summary>
87+
[Obsolete("Replaced by useFogOpacityOcclusion.")]
7588
public bool useBackgroundCloudOcclusion = false;
89+
90+
/// <summary>Enable Occlusion using fog opacity from volumetric clouds, cloud layers and fog.</summary>
91+
[FormerlySerializedAs("volumetricCloudOcclusion")]
92+
public bool useFogOpacityOcclusion = false;
7693
/// <summary>
7794
/// Enable Occlusion with Water
7895
/// </summary>
@@ -103,7 +120,9 @@ public LensFlareDataSRP lensFlareData
103120
public bool allowOffScreen = false;
104121
/// <summary>
105122
/// If volumetricCloudOcclusion is true then use the volumetric cloud (on HDRP only) for the occlusion
123+
/// Please use useFogOpacityOcclusion instead.
106124
/// </summary>
125+
[Obsolete("Please use useFogOpacityOcclusion instead.")]
107126
public bool volumetricCloudOcclusion = false;
108127

109128
/// Our default celestial body will have an angular radius of 3.3 degrees. This is an arbitrary number, but must be kept constant

Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareDataSRP.cs.hlsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
#ifndef LENSFLAREDATASRP_CS_HLSL
66
#define LENSFLAREDATASRP_CS_HLSL
7+
//
8+
// UnityEngine.Rendering.SRPLensFlareColorType: static fields
9+
//
10+
#define SRPLENSFLARECOLORTYPE_CONSTANT (0)
11+
#define SRPLENSFLARECOLORTYPE_RADIAL_GRADIENT (1)
12+
#define SRPLENSFLARECOLORTYPE_ANGULAR_GRADIENT (2)
13+
714
//
815
// UnityEngine.Rendering.SRPLensFlareType: static fields
916
//

Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareOcclusionPermutation.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ namespace UnityEngine.Rendering
44
internal enum LensFlareOcclusionPermutation
55
{
66
Depth = (1 << 0),
7-
CloudLayer = (1 << 1),
8-
VolumetricCloud = (1 << 2),
7+
FogOpacity = (1 << 2),
98
Water = (1 << 3)
109
}
1110
}

Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareOcclusionPermutation.cs.hlsl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
// UnityEngine.Rendering.LensFlareOcclusionPermutation: static fields
99
//
1010
#define LENSFLAREOCCLUSIONPERMUTATION_DEPTH (1)
11-
#define LENSFLAREOCCLUSIONPERMUTATION_CLOUD_LAYER (2)
12-
#define LENSFLAREOCCLUSIONPERMUTATION_VOLUMETRIC_CLOUD (4)
11+
#define LENSFLAREOCCLUSIONPERMUTATION_FOG_OPACITY (4)
1312
#define LENSFLAREOCCLUSIONPERMUTATION_WATER (8)
1413

1514

Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/LensFlareCommon.hlsl

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ SAMPLER(sampler_StencilTexture);
4848
TEXTURE2D_X(_DepthWithWaterTexture);
4949
SAMPLER(sampler_DepthWithWaterTexture);
5050

51-
TEXTURE2D_X(_FlareCloudOpacity);
52-
SAMPLER(sampler_FlareCloudOpacity);
53-
5451
TEXTURE2D_X(_FlareSunOcclusionTex);
5552
SAMPLER(sampler_FlareSunOcclusionTex);
5653

@@ -204,7 +201,7 @@ float GetOcclusion(float ratio)
204201
{
205202
float depth0 = GetLinearDepthValue(pos);
206203

207-
#if UNITY_REVERSED_Z
204+
#if UNITY_REVERSED_Z
208205
if (depth0 > _ScreenPosZ)
209206
#else
210207
if (depth0 < _ScreenPosZ)
@@ -213,24 +210,14 @@ float GetOcclusion(float ratio)
213210
float occlusionValue = 1.0f;
214211

215212
#ifdef HDRP_FLARE
216-
if ((_FlareOcclusionPermutation & LENSFLAREOCCLUSIONPERMUTATION_CLOUD_LAYER) != 0)
217-
{
218-
float cloudOpacity;
219-
if (_ViewId >= 0)
220-
cloudOpacity = LOAD_TEXTURE2D_ARRAY(_FlareCloudOpacity, uint2(pos * _ScreenParams.xy), _ViewId).x;
221-
else
222-
cloudOpacity = LOAD_TEXTURE2D_X(_FlareCloudOpacity, uint2(pos * _ScreenParams.xy)).x;
223-
occlusionValue *= saturate(cloudOpacity);
224-
}
225-
226-
if ((_FlareOcclusionPermutation & LENSFLAREOCCLUSIONPERMUTATION_VOLUMETRIC_CLOUD) != 0)
213+
if ((_FlareOcclusionPermutation & LENSFLAREOCCLUSIONPERMUTATION_FOG_OPACITY) != 0)
227214
{
228-
float volumetricCloudOcclusion;
215+
float fogOcclusion;
229216
if (_ViewId >= 0)
230-
volumetricCloudOcclusion = SAMPLE_TEXTURE2D_ARRAY_LOD(_FlareSunOcclusionTex, sampler_FlareSunOcclusionTex, pos, _ViewId, 0).w;
217+
fogOcclusion = SAMPLE_TEXTURE2D_ARRAY_LOD(_FlareSunOcclusionTex, sampler_FlareSunOcclusionTex, pos * _RTHandleScale.xy, _ViewId, 0).x;
231218
else
232-
volumetricCloudOcclusion = SAMPLE_TEXTURE2D_X_LOD(_FlareSunOcclusionTex, sampler_FlareSunOcclusionTex, pos, 0).w;
233-
occlusionValue *= saturate(volumetricCloudOcclusion);
219+
fogOcclusion = SAMPLE_TEXTURE2D_X_LOD(_FlareSunOcclusionTex, sampler_FlareSunOcclusionTex, pos * _RTHandleScale.xy, 0).x;
220+
occlusionValue *= saturate(fogOcclusion);
234221
}
235222

236223
if ((_FlareOcclusionPermutation & LENSFLAREOCCLUSIONPERMUTATION_WATER) != 0)

Packages/com.unity.render-pipelines.high-definition/Editor/Sky/AtmosphericScattering/FogEditor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class FogEditor : VolumeComponentWithQualityEditor
2323

2424
protected SerializedDataParameter m_EnableVolumetricFog;
2525
protected SerializedDataParameter m_Anisotropy;
26+
protected SerializedDataParameter m_MultipleScatteringIntensity;
2627
protected SerializedDataParameter m_DepthExtent;
2728
protected SerializedDataParameter m_GlobalLightProbeDimmer;
2829
protected SerializedDataParameter m_SliceDistributionUniformity;
@@ -63,7 +64,9 @@ public override void OnEnable()
6364
m_BaseHeight = Unpack(o.Find(x => x.baseHeight));
6465
m_MaximumHeight = Unpack(o.Find(x => x.maximumHeight));
6566
m_Anisotropy = Unpack(o.Find(x => x.anisotropy));
67+
m_MultipleScatteringIntensity = Unpack(o.Find(x => x.multipleScatteringIntensity));
6668
m_GlobalLightProbeDimmer = Unpack(o.Find(x => x.globalLightProbeDimmer));
69+
6770
m_EnableVolumetricFog = Unpack(o.Find(x => x.enableVolumetricFog));
6871
m_DepthExtent = Unpack(o.Find(x => x.depthExtent));
6972
m_SliceDistributionUniformity = Unpack(o.Find(x => x.sliceDistributionUniformity));
@@ -165,6 +168,8 @@ public override void OnInspectorGUI()
165168
}
166169
EndAdditionalPropertiesScope();
167170
}
171+
172+
PropertyField(m_MultipleScatteringIntensity);
168173
}
169174
}
170175
}

Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/Fog.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ public class Fog : VolumeComponentWithQuality
7575
[Tooltip("Controls the distribution of slices along the Camera's focal axis. 0 is exponential distribution and 1 is linear distribution.")]
7676
public ClampedFloatParameter sliceDistributionUniformity = new ClampedFloatParameter(0.75f, 0, 1);
7777

78+
/// <summary>Controls how much the multiple-scattering will affect the scene. Directly controls the amount of blur depending on the fog density.</summary>
79+
[AdditionalProperty]
80+
[Tooltip("Use this value to simulate multiple scattering when combining the fog with the scene color.")]
81+
public ClampedFloatParameter multipleScatteringIntensity = new ClampedFloatParameter(0.0f, 0.0f, 2.0f);
82+
7883
// Limit parameters for the fog quality
7984
internal const float minFogScreenResolutionPercentage = (1.0f / 16.0f) * 100;
8085
internal const float optimalFogScreenResolutionPercentage = (1.0f / 8.0f) * 100;
@@ -176,6 +181,13 @@ internal static bool IsPBRFogEnabled(HDCamera hdCamera)
176181
return (visualEnv.skyType.value == (int)SkyType.PhysicallyBased) && pbrSky.atmosphericScattering.value && fs;
177182
}
178183

184+
internal static bool IsMultipleScatteringEnabled(HDCamera hdCamera, out float intensity)
185+
{
186+
var fog = hdCamera.volumeStack.GetComponent<Fog>();
187+
intensity = fog.multipleScatteringIntensity.value;
188+
return intensity > 0.0f;
189+
}
190+
179191
static float ScaleHeightFromLayerDepth(float d)
180192
{
181193
// Exp[-d / H] = 0.001

0 commit comments

Comments
 (0)