fix: tune real weather particle rendering
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-09-05 08:34:36 +08:00
parent 8a0873a5fb
commit 6c7886b0c3
11 changed files with 364 additions and 38 deletions

View File

@@ -35,6 +35,12 @@ bool validFieldUv(vec2 uv) {
return all(greaterThanEqual(uv, vec2(0.0))) && all(lessThanEqual(uv, vec2(1.0)));
}
const float EARTH_CIRCUMFERENCE_METERS = 40075016.68557849;
float mercatorLatitudeRadians(float worldY) {
return atan(sinh(3.141592653589793 * (1.0 - 2.0 * worldY)));
}
vec3 weatherSpeedColor(float speed) {
// Fixed 0..30 m/s scale: no per-frame or per-dataset auto stretching.
float t = clamp(speed / 30.0, 0.0, 1.0);
@@ -83,10 +89,16 @@ void main() {
position = seed;
velocity = vec2(0.0);
}
// Field V remains north-positive. Mercator Y increases southward, so
// convert only at the physical-velocity -> map-displacement boundary.
vec2 mercatorVelocity = vec2(velocity.x, -velocity.y);
position = position + mercatorVelocity * u_pass.y * 0.00004;
// U/V remain canonical metres per second. u_pass.y is the explicit
// visual simulation delta in seconds; the validation clock may run
// faster than wall time, but it never changes the field contract.
// Web Mercator x spans Earth's circumference; y additionally scales
// with sec(latitude). V is north-positive while world y is southward.
float latitude = mercatorLatitudeRadians(position.y);
float dx = velocity.x * u_pass.y / EARTH_CIRCUMFERENCE_METERS;
float dy = -velocity.y * u_pass.y /
(EARTH_CIRCUMFERENCE_METERS * max(cos(latitude), 0.01));
position = position + vec2(dx, dy);
if (!validFieldUv(fieldUv(position)) || any(isnan(velocity))) position = seed;
fragColor = vec4(position, fract(previous.b + 0.03125 * u_pass.y), 1.0);
} else if (mode < 1.5) {