16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 04:19:19 +02:00
Files
maszyna/betterRenderer/shaders/manul/sky.hlsli
2025-12-22 21:43:52 +01:00

108 lines
3.7 KiB
HLSL

#ifndef SKY_HLSLI
#define SKY_HLSLI
#include "math.hlsli"
#include "sky_common.hlsli"
Texture2D g_Sky : register(t13);
Texture2DArray<float4> g_AerialPerspectiveLut : register(t14);
SamplerState g_SkySampler : register(s13);
#define SKY_INF 1. #INF
float3 CalcSphereNormal(in float3 viewDir, in float3 sphereDir, in float cosAngularSize);
void CalcSun(inout float3 color, in float3 viewDir, in float3 sunDir, in float altitude)
{
float3 ray_origin = float3(0.0, EARTH_RADIUS + max(altitude, 1.), 0.0);
float ground_dist = ray_sphere_intersection(ray_origin, viewDir, EARTH_RADIUS);
if (ground_dist < 0.0)
{
if (dot(viewDir, sunDir) > 0.99998869014)
{
color = linear_srgb_from_spectral_samples(sun_spectral_irradiance) * exp(-2.);
}
}
}
void CalcMoon(inout float3 color, in float3 viewDir, in float3 moonDir, in float3 sunDir, in float altitude)
{
float3 ray_origin = float3(0.0, EARTH_RADIUS + max(altitude, 1.), 0.0);
float ground_dist = ray_sphere_intersection(ray_origin, viewDir, EARTH_RADIUS);
if (ground_dist < 0.0)
{
float3 normal = CalcSphereNormal(viewDir, moonDir, 0.99998869014);
if (dot(normal, normal) > 0.)
{
color = .07 * max(dot(normal, sunDir), 0.) * linear_srgb_from_spectral_samples(sun_spectral_irradiance) * exp(-2.);
}
}
}
float3 CalcSphereNormal(in float3 viewDir, in float3 sphereDir, in float cosAngularSize)
{
float sqrSinAngularSize = 1. - cosAngularSize * cosAngularSize;
float tca = dot(sphereDir, viewDir);
float d2 = dot(sphereDir, sphereDir) - tca * tca;
if (d2 > sqrSinAngularSize)
return (float3)(0.);
float thc = sqrt(sqrSinAngularSize - d2);
float t = tca - thc;
if (t < 0.)
return (float3)(0.);
float3 p = viewDir * t;
return normalize(p - sphereDir);
}
float2 CalcEquirectangularCoords(in float3 viewDir, in float3 sunDir, in float2 size)
{
float2 uv_scale = float2(1., 1. - 1. / size.y);
// float lon = acos(clamp(dot(normalize(sunDir.xz), normalize(viewDir.xz)), -1., 1.));
float lon = atan2(-viewDir.z, -viewDir.x);
float lat = asin(viewDir.y);
return float2(InvLerp(-PI, PI, lon), InvLerp(PI_OVER_TWO, -PI_OVER_TWO, lat)) * uv_scale;
}
float2 CalcEquirectangularCoordsBottomClipped(in float3 viewDir, in float3 sunDir, in float2 size)
{
float2 uv_scale = float2(1., 1. - 1. / size.y);
// float lon = acos(clamp(dot(normalize(sunDir.xz), normalize(viewDir.xz)), -1., 1.));
float lon = atan2(-viewDir.z, -viewDir.x);
float lat = asin(viewDir.y);
return float2(InvLerp(-PI, PI, lon), InvLerp(PI_OVER_TWO, -.125 * PI_OVER_TWO, lat)) * uv_scale;
}
void CalcAtmosphere(inout float3 color, in float3 viewDir, in float3 sunDir)
{
uint2 size;
g_Sky.GetDimensions(size.x, size.y);
float4 sky = g_Sky.SampleLevel(g_SkySampler, CalcEquirectangularCoordsBottomClipped(viewDir, sunDir, size), 0.);
color = color * sky.a + sky.rgb;
}
void ApplyAerialPerspective(inout float3 color, in float alpha, in float3 viewDir, in float3 sunDir, in float depth)
{
uint3 size;
g_AerialPerspectiveLut.GetDimensions(size.x, size.y, size.z);
float slice = sqrt(depth) * size.z;
float slice_factor = frac(slice);
slice -= 1.;
float2 uv = CalcEquirectangularCoords(viewDir, sunDir, size.xy);
float4 sample_near = slice > 0. ? g_AerialPerspectiveLut.SampleLevel(g_SkySampler, float3(uv, floor(slice)), 0.) : float4(0., 0., 0., 1.);
float4 sample_far = g_AerialPerspectiveLut.SampleLevel(g_SkySampler, float3(uv, ceil(slice)), 0.);
float4 aerial = lerp(sample_near, sample_far, slice_factor);
color = color * aerial.a + aerial.rgb * alpha;
}
#endif