Skip to content

Fix light flare for pbr sky #6278

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,12 @@ private void ConvertDirectionalLightToGPUFormat(

lightData.flareSize = Mathf.Max(lightRenderData.flareSize * Mathf.Deg2Rad, 5.960464478e-8f);
lightData.flareFalloff = lightRenderData.flareFalloff;

// On some vendors trigonometry has very bad precision, so we precompute what we can on CPU to avoid precision issues (case 1369376).
float radInner = 0.5f * lightData.angularDiameter;
lightData.flareCosInner = Mathf.Cos(radInner);
lightData.flareCosOuter = Mathf.Cos(radInner + lightData.flareSize);

lightData.flareTint = (Vector3)(Vector4)lightRenderData.flareTint;
lightData.surfaceTint = (Vector3)(Vector4)lightRenderData.surfaceTint;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,16 @@ struct DirectionalLightData

public float diffuseDimmer;
public float specularDimmer;

public float penumbraTint;
public float isRayTracedContactShadow;

public float distanceFromCamera; // -1 -> no sky interaction
public float angularDiameter; // Units: radians

public float flareFalloff;
public float flareCosInner;
public float flareCosOuter;
public float __unused__;

public Vector3 flareTint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ struct DirectionalLightData
float distanceFromCamera;
float angularDiameter;
float flareFalloff;
float flareCosInner;
float flareCosOuter;
float __unused__;
float3 flareTint;
float flareSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,6 @@ static class HDShaderIDs
public static readonly int _SpaceEmissionMultiplier = Shader.PropertyToID("_SpaceEmissionMultiplier");

public static readonly int _RenderSunDisk = Shader.PropertyToID("_RenderSunDisk");
public static readonly int _SunDiskCosines = Shader.PropertyToID("_SunDiskCosines");

public static readonly int _ColorSaturation = Shader.PropertyToID("_ColorSaturation");
public static readonly int _AlphaSaturation = Shader.PropertyToID("_AlphaSaturation");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Shader "Hidden/HDRP/Sky/PbrSky"

#pragma vertex Vert

// #pragma enable_d3d11_debug_symbols
#pragma editor_sync_compilation
#pragma target 4.5
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
Expand All @@ -25,13 +26,6 @@ Shader "Hidden/HDRP/Sky/PbrSky"
float _GroundEmissionMultiplier;
float _SpaceEmissionMultiplier;

// Inner and outer cosine computed as:
// float radInner = 0.5 * light.angularDiameter
// float cosInner = cos(radInner); // (In _SunDiskCosines.x)
// float cosOuter = cos(radInner + light.flareSize); // (In _SunDiskCosines.y)
// We need to pass it over instead of computing it here because on some vendors trigonometry has very bad precision, so we precompute what we can on CPU to have better precision.
float4 _SunDiskCosines;

// Sky framework does not set up global shader variables (even per-view ones),
// so they can contain garbage. It's very difficult to not include them, however,
// since the sky framework includes them internally in many header files.
Expand Down Expand Up @@ -118,19 +112,16 @@ Shader "Hidden/HDRP/Sky/PbrSky"
float rad = acos(LdotV);
float radInner = 0.5 * light.angularDiameter;

float cosInner = _SunDiskCosines.x;
float cosOuter = _SunDiskCosines.y;

float solidAngle = TWO_PI * (1 - cosInner);
float solidAngle = TWO_PI * (1 - light.flareCosInner);

if (LdotV >= cosOuter)
if (LdotV >= light.flareCosOuter)
{
// Sun flare is visible. Sun disk may or may not be visible.
// Assume uniform emission.
float3 color = light.color.rgb;
float scale = rcp(solidAngle);

if (LdotV >= cosInner) // Sun disk.
if (LdotV >= light.flareCosInner) // Sun disk.
{
tFrag = lightDist;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,14 +500,6 @@ public override void RenderSky(BuiltinSkyParameters builtinParams, bool renderFo
}
s_PbrSkyMaterialProperties.SetInt(HDShaderIDs._HasSpaceEmissionTexture, hasSpaceEmissionTexture);

// We need to pass it over instead of computing it here because on some vendors trigonometry has very bad precision, so we precompute what we can on CPU to have better precision.
// We can safely retrieve HDAdditionalLightData as for PBR sky the sunlight is always going to be an HDRP light.
var lightData = builtinParams.sunLight.gameObject.GetComponent<HDAdditionalLightData>();
float radInner = 0.5f * lightData.angularDiameter * Mathf.Deg2Rad;
float cosInner = Mathf.Cos(radInner);
float cosOuter = Mathf.Cos(radInner + lightData.flareSize);
s_PbrSkyMaterialProperties.SetVector(HDShaderIDs._SunDiskCosines, new Vector4(cosInner, cosOuter, 0, 0));

s_PbrSkyMaterialProperties.SetInt(HDShaderIDs._RenderSunDisk, renderSunDisk ? 1 : 0);

int pass = (renderForCubemap ? 0 : 2);
Expand Down
6 changes: 3 additions & 3 deletions com.unity.template-hd/Assets/Scenes/SampleScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -28899,9 +28899,9 @@ MonoBehaviour:
m_UseScreenSpaceShadows: 0
m_InteractsWithSky: 1
m_AngularDiameter: 0.53
m_FlareSize: 0
m_FlareTint: {r: 0, g: 0, b: 0, a: 1}
m_FlareFalloff: 0
m_FlareSize: 2
m_FlareTint: {r: 1, g: 1, b: 1, a: 1}
m_FlareFalloff: 4
m_SurfaceTexture: {fileID: 0}
m_SurfaceTint: {r: 1, g: 1, b: 1, a: 1}
m_Distance: 150000000
Expand Down