1const sun_angular_size = 1.0 * (PI / 180.0);
2
3fn dir_in_cone(u: vec2f) -> vec3<f32> {
4 let sun_cos_theta_max = cos(0.255f * PI / 180f);
5 let cos_theta = 1f - u.x * (1f - sun_cos_theta_max);
6 let sin_theta = sqrt(1f - cos_theta * cos_theta);
7 let phi = 2f * PI * u.y;
8 let x = cos(phi) * sin_theta;
9 let y = sin(phi) * sin_theta;
10 let z = cos_theta;
11 return vec3(x, y, z);
12}
13
14fn sample_sun_cone_dir(u: vec2f) -> vec3<f32> {
15 let v = dir_in_cone(u);
16 let onb = pixar_onb(normalize(uniforms.sun_direction));
17 return normalize(onb * v);
18}
19
20// https://www.jcgt.org/published/0006/01/01/paper-lowres.pdf
21fn pixar_onb(n: vec3f) -> mat3x3<f32> {
22 let s = select(- 1f, 1f, n.z >= 0f);
23 let a = - 1f / (s + n.z);
24 let b = n.x * n.y * a;
25 let u = vec3(1f + s * n.x * n.x * a, s * b, - s * n.x);
26 let v = vec3(b, s + n.y * n.y * a, - n.y);
27 return mat3x3(u, v, n);
28}
29
30// simplified approximation of preetham
31fn sky_glow(dir: vec3f, sun_dir: vec3f) -> vec3f {
32 let view_dir = normalize(dir);
33 let sun_dir_n = normalize(sun_dir);
34 let cos_theta = dot(view_dir, sun_dir_n);
35 if sun_dir_n.z <= 0.0 {
36 return vec3f(0.0);
37 }
38 // sun altitude still helps modulate overall warmth
39 let sun_altitude = clamp(sun_dir_n.z, 0.0, 1.0);
40 // more saturated warm tone for horizon, and deeper blue for zenith
41 let horizon_color = vec3f(1.1, 0.4, 0.2);
42 // rich orange
43 let zenith_color = vec3f(0.05, 0.2, 0.6);
44 // deep blue
45 // exaggerated curve to preserve saturation
46 let sky_color = mix(horizon_color, zenith_color, pow(sun_altitude, 0.1));
47 // rayleigh-like gradient with vertical bias
48 let rayleigh = sky_color * (0.6 + 0.4 * cos_theta * cos_theta);
49 // warm sun glow with stronger color (no gray falloff)
50 let mie = vec3f(1.3, 0.6, 0.3) * pow(max(cos_theta, 0.0), 12.0) * 0.6;
51 return clamp(rayleigh + mie, vec3f(0.0), vec3f(100.0));
52}
53
54fn sun_glow(dir: vec3f, sun_dir: vec3f) -> vec3f {
55 let view_dir = normalize(dir);
56 let sun_n = normalize(sun_dir);
57 let cos_theta = dot(view_dir, sun_n);
58 // angular radius (half the angular size)
59 let angular_radius = 0.5 * uniforms.sun_angular_size;
60 let inner = cos(angular_radius * 0.9);
61 let outer = cos(angular_radius * 1.1);
62 let sun_disk = smoothstep(outer, inner, max(cos_theta, 0.0));
63 // compute sun altitude (z-up): 0 = horizon, 1 = overhead
64 let sun_altitude = clamp(sun_n.z, 0.0, 1.0);
65 return uniforms.sun_radiance * /*tint*/
66 sun_disk;
67}