44 lines
1.8 KiB
GLSL
44 lines
1.8 KiB
GLSL
#version 450 core
|
|
#include "common.glsl"
|
|
// Fully procedural rain: each instance is one streak in a box that follows
|
|
// the camera target. Drops are fixed in world space (the box wraps around
|
|
// them), fall at uWeather.z and slant with the wind.
|
|
|
|
uniform vec3 uRainCenter;
|
|
uniform vec2 uRainBox; // half extent (xz), height
|
|
|
|
out vec2 vLocal; // x across the streak (-1..1), y along it (0 = head)
|
|
out float vAlpha;
|
|
|
|
void main() {
|
|
int id = gl_InstanceID;
|
|
vec3 h = vec3(hash12(vec2(float(id), 1.37)), hash12(vec2(float(id), 7.13)), hash12(vec2(float(id), 3.71)));
|
|
float E = uRainBox.x, H = uRainBox.y;
|
|
float speed = uWeather.z * (0.85 + 0.3 * h.x);
|
|
vec2 wdir = normalize(uWind.xy + 1e-5);
|
|
vec3 vel = vec3(wdir.x, 0.0, wdir.y) * uWind.z * 28.0 + vec3(0.0, -speed, 0.0);
|
|
|
|
float age = fract(h.y + uTime * speed / H); // 0 = top of the box
|
|
float tFall = age * H / speed;
|
|
vec3 p;
|
|
p.y = uRainCenter.y + H * 0.75 - age * H;
|
|
vec2 base = h.xz * 2.0 * E + vel.xz * tFall;
|
|
p.xz = uRainCenter.xz + mod(base - uRainCenter.xz + E, 2.0 * E) - E;
|
|
|
|
vec3 dir = normalize(vel);
|
|
float len = speed * 0.032;
|
|
vec3 toCam = uCamPos.xyz - p;
|
|
float dist = length(toCam);
|
|
vec3 side = normalize(cross(dir, toCam / max(dist, 1e-3)));
|
|
float width = 0.008 + dist * 0.0006; // never thinner than ~1 px
|
|
|
|
vec2 corner = vec2(float(gl_VertexID & 1) * 2.0 - 1.0, float(gl_VertexID >> 1));
|
|
vec3 wp = p - dir * len * corner.y + side * width * corner.x;
|
|
|
|
vLocal = corner;
|
|
// Fade near the camera (big blurry drops) and at the box edges.
|
|
vec2 rel = abs(p.xz - uRainCenter.xz) / E;
|
|
vAlpha = smoothstep(1.5, 5.0, dist) * (1.0 - smoothstep(0.75, 1.0, max(rel.x, rel.y))) * (0.6 + 0.4 * h.z);
|
|
gl_Position = uViewProj * vec4(wp, 1.0);
|
|
}
|