Kelsidavis-WoWee/assets/shaders/clouds.frag.glsl
Kelsi 4fc3689dcc Fix sky and clouds orientation for Z-up world coordinates
Skybox: replace sphere-mesh approach with a fullscreen triangle that
reconstructs the world-space ray direction analytically via inverse
projection/view matrices. Eliminates clip.w=0 degeneracy at the horizon
and correctly maps altitude to dir.z in the Z-up coordinate system.

Clouds: hemisphere mesh was storing altitude in aPos.y (Y-up convention);
the Z-up view matrix projected this sideways, making clouds appear
vertical. Store altitude in aPos.z and update the fragment shader to
read dir.z as altitude and dir.xy as the horizontal UV plane.
2026-02-21 22:04:17 -08:00

63 lines
1.5 KiB
GLSL

#version 450
layout(push_constant) uniform Push {
vec4 cloudColor;
float density;
float windOffset;
} push;
layout(location = 0) in vec3 vWorldDir;
layout(location = 0) out vec4 outColor;
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}
float fbm(vec2 p) {
float val = 0.0;
float amp = 0.5;
for (int i = 0; i < 4; i++) {
val += amp * noise(p);
p *= 2.0;
amp *= 0.5;
}
return val;
}
void main() {
vec3 dir = normalize(vWorldDir);
float altitude = dir.z; // Z is up in the Z-up world coordinate system
if (altitude < 0.0) discard;
vec2 uv = dir.xy / (altitude + 0.001); // XY is the horizontal plane
uv += push.windOffset;
float cloud1 = fbm(uv * 0.8);
float cloud2 = fbm(uv * 1.6 + 5.0);
float cloud = cloud1 * 0.7 + cloud2 * 0.3;
cloud = smoothstep(0.35, 0.65, cloud) * push.density;
float edgeBreak = noise(uv * 4.0);
cloud *= smoothstep(0.2, 0.5, edgeBreak);
float horizonFade = smoothstep(0.0, 0.15, altitude);
cloud *= horizonFade;
float edgeSoftness = smoothstep(0.0, 0.3, cloud);
float alpha = cloud * edgeSoftness;
if (alpha < 0.01) discard;
outColor = vec4(push.cloudColor.rgb, alpha);
}