Skip to content

Fix NaN on Intel GPU when using PBR Sky and rendering sun disk #6145

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 6 commits into from
Nov 5, 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 @@ -573,6 +573,7 @@ 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,7 +4,6 @@ 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 @@ -26,6 +25,13 @@ 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 @@ -111,8 +117,9 @@ Shader "Hidden/HDRP/Sky/PbrSky"
float LdotV = -dot(L, V);
float rad = acos(LdotV);
float radInner = 0.5 * light.angularDiameter;
float cosInner = cos(radInner);
float cosOuter = cos(radInner + light.flareSize);

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

float solidAngle = TWO_PI * (1 - cosInner);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,14 @@ 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