Files
rogue/assets/shaders/raytrace/sky.slang
2026-04-19 18:50:03 -03:00

118 lines
3.4 KiB
Plaintext

#ifndef SKY_SLANG
#define SKY_SLANG
namespace rt {
struct sky_config {
float turbidity;
// = 2.0;
float azimuth; // = 0.25f;
float inclination; // = 1.0f;
};
float3 YxyToXYZ(
in const float3 Yxy) {
let Y = Yxy.r;
let x = Yxy.g;
let y = Yxy.b;
let X = x * ( Y / y );
let Z = ( 1.0 - x - y ) * ( Y / y );
return float3(X, Y, Z);
}
float3 XYZToRGB(
in const float3 XYZ) {
let M = float3x3(
2.3706743, -0.5138850, 0.0052982,
-0.9000405, 1.4253036, -0.0146949,
-0.4706338, 0.0885814, 1.0093968
);
return mul(XYZ, M);
}
float3 YxyToRGB(
in const float3 Yxy) {
let XYZ = YxyToXYZ( Yxy );
let RGB = XYZToRGB( XYZ );
return RGB;
}
void calculatePerezDistribution(
in const float t,
out float3 A,
out float3 B,
out float3 C,
out float3 D,
out float3 E) {
A = float3( 0.1787 * t - 1.4630, -0.0193 * t - 0.2592, -0.0167 * t - 0.2608 );
B = float3( -0.3554 * t + 0.4275, -0.0665 * t + 0.0008, -0.0950 * t + 0.0092 );
C = float3( -0.0227 * t + 5.3251, -0.0004 * t + 0.2125, -0.0079 * t + 0.2102 );
D = float3( 0.1206 * t - 2.5771, -0.0641 * t - 0.8989, -0.0441 * t - 1.6537 );
E = float3( -0.0670 * t + 0.3703, -0.0033 * t + 0.0452, -0.0109 * t + 0.0529 );
}
float3 calculateZenithLuminanceYxy(
in const float t,
in const float thetaS) {
let chi = ( 4.0 / 9.0 - t / 120.0 ) * ( 3.14159f - 2.0 * thetaS );
let Yz = ( 4.0453 * t - 4.9710 ) * tan( chi ) - 0.2155 * t + 2.4192;
let theta2 = thetaS * thetaS;
let theta3 = theta2 * thetaS;
let T = t;
let T2 = t * t;
let xz =
( 0.00165 * theta3 - 0.00375 * theta2 + 0.00209 * thetaS + 0.0) * T2 +
(-0.02903 * theta3 + 0.06377 * theta2 - 0.03202 * thetaS + 0.00394) * T +
( 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * thetaS + 0.25886);
let yz =
( 0.00275 * theta3 - 0.00610 * theta2 + 0.00317 * thetaS + 0.0) * T2 +
(-0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * thetaS + 0.00516) * T +
( 0.15346 * theta3 - 0.26756 * theta2 + 0.06670 * thetaS + 0.26688);
return float3( Yz, xz, yz );
}
float3 calculatePerezLuminanceYxy(
in const float theta,
in const float gamma,
in const float3 A,
in const float3 B,
in const float3 C,
in const float3 D,
in const float3 E) {
return ( 1.0 + A * exp( B / cos( theta ) ) ) * ( 1.0 + C * exp( D * gamma ) + E * cos( gamma ) * cos( gamma ) );
}
float3 calculateSkyLuminanceRGB(
in const float3 s,
in const float3 e,
in const float t) {
float3 A, B, C, D, E;
calculatePerezDistribution( t, A, B, C, D, E );
let thetaS = acos( saturate(dot(s, float3(0, 1, 0))));
let thetaE = acos( saturate(dot(e, float3(0, 1, 0))));
let gammaE = acos( saturate(dot(s, e)));
let Yz = calculateZenithLuminanceYxy( t, thetaS );
let fThetaGamma = calculatePerezLuminanceYxy( thetaE, gammaE, A, B, C, D, E );
let fZeroThetaS = calculatePerezLuminanceYxy( 0.0, thetaS, A, B, C, D, E );
let Yp = Yz * ( fThetaGamma / fZeroThetaS );
return YxyToRGB( Yp );
}
float3 evaluate_sky(
in const float3 w_i,
in const sky_config config) {
let sun_dir = normalize(float3(
sin(config.inclination) * cos(config.azimuth),
cos(config.inclination),
sin(config.inclination) * sin(config.azimuth)));
return calculateSkyLuminanceRGB(sun_dir, w_i, config.turbidity) * 0.05f;
}
}
#endif