big
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
#ifndef ANIME_CLOUDS_INCLUDED
|
||||
#define ANIME_CLOUDS_INCLUDED
|
||||
|
||||
// Organic 2D cloud field shared by the actual Sky shader and the fullscreen
|
||||
// ink composite. Broad domain-warped masses define the cloud, a second rotated
|
||||
// octave breaks up its contour into billows, and a quiet high-frequency layer
|
||||
// erodes the edge. Unlike a grid of radial primitives, no stage exposes a
|
||||
// circle or a square as the final silhouette.
|
||||
|
||||
float cloud_hash(vec2 p) {
|
||||
// Sine-free hash: substantially cheaper when the field is sampled several
|
||||
// times to estimate the direction the sun meets the cloud.
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
|
||||
float cloud_noise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
// Quintic interpolation keeps both the value and its slope continuous at
|
||||
// cell boundaries, so a density threshold cannot reveal the noise grid.
|
||||
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
|
||||
float a = cloud_hash(i);
|
||||
float b = cloud_hash(i + vec2(1.0, 0.0));
|
||||
float c = cloud_hash(i + vec2(0.0, 1.0));
|
||||
float d = cloud_hash(i + vec2(1.0, 1.0));
|
||||
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
||||
}
|
||||
|
||||
|
||||
float cloud_fbm(vec2 p) {
|
||||
mat2 turn = mat2(vec2(0.80, 0.60), vec2(-0.60, 0.80));
|
||||
float value = cloud_noise(p) * 0.52;
|
||||
p = turn * p * 2.03 + vec2(9.17, 4.31);
|
||||
value += cloud_noise(p) * 0.27;
|
||||
p = turn * p * 2.07 + vec2(3.73, 12.61);
|
||||
value += cloud_noise(p) * 0.14;
|
||||
p = turn * p * 2.01 + vec2(15.19, 7.07);
|
||||
value += cloud_noise(p) * 0.07;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
float cloud_detail(vec2 p) {
|
||||
mat2 turn = mat2(vec2(0.86, 0.51), vec2(-0.51, 0.86));
|
||||
return cloud_noise(turn * p * 2.75 + vec2(23.7, 6.1)) * 0.68
|
||||
+ cloud_noise(p * 5.20 + vec2(2.9, 31.4)) * 0.32;
|
||||
}
|
||||
|
||||
|
||||
float cloud_field(vec2 p) {
|
||||
// Low-frequency vector warp makes the mass curl and fork without making
|
||||
// the outline busy. The two components use unrelated offsets so this does
|
||||
// not merely slide the source noise along its own contour.
|
||||
vec2 domain = p * 0.34;
|
||||
vec2 warp = vec2(
|
||||
cloud_noise(domain + vec2(17.2, 4.8)),
|
||||
cloud_noise(domain + vec2(3.1, 29.6))) - 0.5;
|
||||
vec2 q = p + warp * 1.35;
|
||||
|
||||
float mass = cloud_fbm(q * 0.52);
|
||||
float billows = cloud_fbm(
|
||||
mat2(vec2(0.74, 0.67), vec2(-0.67, 0.74)) * q * 1.18
|
||||
+ vec2(11.3, 8.7));
|
||||
float erosion = cloud_detail(q);
|
||||
float density = mass * 0.70 + billows * 0.24 + erosion * 0.06;
|
||||
|
||||
// A third, much broader field separates the weather into distinct banks.
|
||||
// Without this macro mask a perfectly organic contour can still connect
|
||||
// across half the dome and read as one enormous sheet instead of clouds.
|
||||
float islands = cloud_fbm(q * 0.24 + vec2(41.7, 18.3));
|
||||
return density - (1.0 - islands) * 0.16;
|
||||
}
|
||||
|
||||
|
||||
float cloud_sun_response(vec2 p, vec3 sun_direction) {
|
||||
// Treat density as a painted height field. Sampling a short distance toward
|
||||
// and away from the sun tells us which edge faces it. This gives the cloud
|
||||
// a bright leading rim and a colored lee side, and naturally reverses when
|
||||
// the DirectionalLight turns.
|
||||
vec2 sun_xz = sun_direction.xz;
|
||||
float horizontal = length(sun_xz);
|
||||
vec2 axis = horizontal > 0.0001
|
||||
? sun_xz / horizontal : vec2(0.7071, 0.7071);
|
||||
float toward = cloud_field(p + axis * 0.075);
|
||||
float away = cloud_field(p - axis * 0.075);
|
||||
float directional_slope = (away - toward) / 0.15;
|
||||
// A high sun lights more of the cloud face; a low sun makes the directional
|
||||
// division stronger and leaves a broader colored underside.
|
||||
float overhead = clamp(sun_direction.y, 0.0, 1.0);
|
||||
return smoothstep(-0.22, 0.22, directional_slope + overhead * 0.08);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user