TaggedEngine/shaders/rain.frag

137 lines
4.5 KiB
GLSL

#define PI 3.14159265
#pragma glslify: import("./imports/commonUniforms.glsl")
#pragma glslify: random = require("./requires/random1d")
extern vec2 u_mouse;
extern vec2 u_resolution;
extern float u_time;
float rand( float x )
{
// setup
float i = floor(x);
float f = fract(x);
float s = sign(fract(x/2.0)-0.5);
// use some hash to create a random value k in [0..1] from i
//float k = hash(uint(i));
//float k = 0.5+0.5*sin(i);
float k = fract(i*.1731);
// quartic polynomial
return s*f*(f-1.0)*((16.0*k-4.0)*f*(f-1.0)-1.0);
}
/*
* Returns a random drop position for the given seed value
*/
vec2 random_drop_pos(float val, vec2 screen_dim, vec2 velocity) {
float max_x_move = velocity.x * abs(screen_dim.y / velocity.y);
float x = -max_x_move * step(0.0, max_x_move) + (screen_dim.x + abs(max_x_move)) * rand(val);
float y = (1.0 + 0.05 * rand(1.234 * val)) * screen_dim.y;
return vec2(x, y);
}
/*
* Calculates the drop trail color at the given pixel position
*/
vec3 trail_color(vec2 pixel, vec2 pos, vec2 velocity_dir, float width, float size) {
vec2 pixel_dir = pixel - pos;
float projected_dist = dot(pixel_dir, -velocity_dir);
float tanjential_dist_sq = dot(pixel_dir, pixel_dir) - pow(projected_dist, 2.0);
float width_sq = pow(width, 2.0);
float line = step(0.0, projected_dist) * (1.0 - smoothstep(width_sq / 2.0, width_sq, tanjential_dist_sq));
float dashed_line = line * step(0.5, cos(0.3 * projected_dist - PI / 3.0));
float fading_dashed_line = dashed_line * (1.0 - smoothstep(size / 5.0, size, projected_dist));
return vec3(fading_dashed_line);
}
/*
* Calculates the drop wave color at the given pixel position
*/
vec3 wave_color(vec2 pixel, vec2 pos, float size, float time) {
vec2 pixel_dir = pixel - pos;
float distorted_dist = length(pixel_dir * vec2(1.0, 3.5));
float inner_radius = (0.05 + 0.8 * time) * size;
float outer_radius = inner_radius + 0.25 * size;
float ring = smoothstep(inner_radius, inner_radius + 5.0, distorted_dist)
* (1.0 - smoothstep(outer_radius, outer_radius + 5.0, distorted_dist));
float fading_ring = ring * (1.0 - smoothstep(0.0, 0.7, time));
return vec3(fading_ring);
}
/*
* Calculates the background color at the given pixel position
*/
vec3 background_color(vec2 pixel, vec2 screen_dim, float time) {
return vec3(0.0, 0.0, 1.0 - smoothstep(-1.0, 0.8 + 0.2 * cos(0.5 * time), pixel.y / screen_dim.y));
}
/*
* The main program
*/
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
// Set the total number of rain drops that are visible at a given time
const float n_drops = 20.0;
// Set the drop trail radius
float trail_width = 2.0;
// Set the drop trail size
float trail_size = 70.0;
// Set the drop wave size
float wave_size = 20.0;
// Set the drop fall time in seconds
float fall_time = 0.7;
// Set the drop total life time
float life_time = fall_time + 0.5;
// Set the drop velocity in pixels per second
vec2 velocity = vec2(u_mouse.x - 0.5 * u_resolution.x, -0.9 * u_resolution.y) / fall_time;
vec2 velocity_dir = normalize(velocity);
// Iterate over the drops to calculate the pixel color
vec3 pixel_color = vec3(0.0);
for (float i = 0.0; i < n_drops; ++i) {
// Offset the running time for each drop
float time = u_time + life_time * (i + i / n_drops);
// Calculate the time since the drop appeared on the screen
float ellapsed_time = mod(time, life_time);
// Calculate the drop initial position
vec2 initial_pos = random_drop_pos(i + floor(time / life_time - i) * n_drops, u_resolution, velocity);
// Add the drop to the pixel color
if (ellapsed_time < fall_time) {
// Calculate the drop current position
vec2 current_pos = initial_pos + ellapsed_time * velocity;
// Add the trail color to the pixel color
pixel_color += trail_color(gl_FragCoord.xy, current_pos, velocity_dir, trail_width, trail_size);
} else {
// Calculate the drop final position
vec2 final_pos = initial_pos + fall_time * velocity;
// Add the wave color to the pixel color
pixel_color += wave_color(gl_FragCoord.xy, final_pos, wave_size, ellapsed_time - fall_time);
}
}
// Add the background color to the pixel color
pixel_color += Texel(texture, texture_coords).xyz;
// Fragment shader output
return vec4(pixel_color, 1.0);
}