118 lines
3.4 KiB
Plaintext
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
|