Rasagar/Library/PackageCache/com.unity.render-pipelines.high-definition/Runtime/Sky/PhysicallyBasedSky/PhysicallyBasedSkyRendering.hlsl
2024-08-26 23:07:20 +03:00

100 lines
4.0 KiB
HLSL

#ifndef PHYSICALLY_BASED_SKY_RENDERING_HLSL
#define PHYSICALLY_BASED_SKY_RENDERING_HLSL
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightDefinition.cs.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Sky/PhysicallyBasedSky/PhysicallyBasedSkyCommon.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Sky/SkyUtils.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/AtmosphericScattering/AtmosphericScattering.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/CookieSampling.hlsl"
float3 _PBRSkyCameraPosPS;
int _RenderSunDisk;
float ComputeMoonPhase(CelestialBodyData moon, float3 V)
{
float3 M = moon.forward.xyz * moon.distanceFromCamera;
float radialDistance = moon.distanceFromCamera, rcpRadialDistance = rcp(radialDistance);
float2 t = IntersectSphere(moon.radius, dot(moon.forward.xyz, -V), radialDistance, rcpRadialDistance);
float3 N = normalize(M - t.x * V);
return saturate(-dot(N, moon.sunDirection));
}
float ComputeEarthshine(CelestialBodyData moon)
{
// Approximate earthshine: sun light reflected from earth
// cf. A Physically-Based Night Sky Model
// Compute the percentage of earth surface that is illuminated by the sun as seen from the moon
//float earthPhase = PI - acos(dot(sun.forward.xyz, -light.forward.xyz));
//float earthshine = 1.0f - sin(0.5f * earthPhase) * tan(0.5f * earthPhase) * log(rcp(tan(0.25f * earthPhase)));
// Cheaper approximation of the above (https://www.desmos.com/calculator/11ny6d5j1b)
float sinPhase = sqrt(max(1 - dot(moon.sunDirection, moon.forward), 0.0f)) * INV_SQRT2;
float earthshine = 1.0f - sinPhase * sqrt(sinPhase);
return earthshine * moon.earthshine;
}
float3 RenderSunDisk(inout float tFrag, float tExit, float3 V)
{
float3 radiance = 0;
// Intersect and shade emissive celestial bodies.
// Unfortunately, they don't write depth.
for (uint i = 0; i < _CelestialBodyCount; i++)
{
CelestialBodyData light = _CelestialBodyDatas[i];
// Celestial body must be outside the atmosphere (request from Pierre D).
float lightDist = max(light.distanceFromCamera, tExit);
if (asint(light.angularRadius) != 0 && lightDist < tFrag)
{
// We may be able to see the celestial body.
float3 L = -light.forward.xyz;
float LdotV = -dot(L, V);
float radInner = light.angularRadius;
if (LdotV >= light.flareCosInner) // Sun disk.
{
tFrag = lightDist;
float3 color = light.surfaceColor;
if (light.type != 0)
color *= ComputeMoonPhase(light, V) * INV_PI + ComputeEarthshine(light); // Lambertian BRDF
if (light.surfaceTextureScaleOffset.x > 0)
{
float2 proj = float2(dot(V, light.right), dot(V, light.up));
float2 angles = float2(FastASin(proj.x), FastASin(-proj.y));
float2 uv = angles * rcp(radInner) * 0.5 + 0.5;
color *= SampleCookie2D(uv, light.surfaceTextureScaleOffset);
}
radiance = color;
}
else if (LdotV >= light.flareCosOuter) // Flare region.
{
float rad = acos(LdotV);
float r = max(0, rad - radInner);
float w = saturate(1 - r * rcp(light.flareSize));
float3 color = light.flareColor;
color *= SafePositivePow(w, light.flareFalloff);
radiance += color;
}
}
}
return radiance;
}
#endif // PHYSICALLY_BASED_SKY_RENDERING_HLSL