63 lines
2.2 KiB
GLSL
63 lines
2.2 KiB
GLSL
shader_type canvas_item;
|
|
render_mode unshaded, blend_disabled;
|
|
|
|
uniform sampler2D previous_frame;
|
|
|
|
uniform float water_height = 0.6;
|
|
|
|
uniform float height_damping = 0.13;
|
|
uniform float velocity_damping = 0.8;
|
|
uniform float spread = 0.94;
|
|
|
|
// Height and Velocity are encoded in two components each, so RG is height and BA is velocity.
|
|
// This is needed to get a workable accuracy.
|
|
float read_height(sampler2D tex, vec2 uv) {
|
|
return texture(tex, uv).r + texture(tex, uv).g / 255.0;
|
|
}
|
|
float read_velocity(sampler2D tex, vec2 uv) {
|
|
return texture(tex, uv).b + texture(tex, uv).a / 255.0;
|
|
}
|
|
float get_encoded_remainder(float num) {
|
|
return fract(num * 255.0);
|
|
}
|
|
|
|
void fragment() {
|
|
// Read values here
|
|
float height_here = read_height(previous_frame, UV);
|
|
float velocity_here = read_velocity(previous_frame, UV);
|
|
|
|
// Apply force towards the base height
|
|
// This follows from the damped harmonic oscillator equation F = -kx-bv
|
|
float force = -height_damping * (height_here - water_height) - velocity_here * velocity_damping;
|
|
float acceleration_here = force;
|
|
|
|
// In addition to each individual height behaving like a spring, neighbouring heights are
|
|
// "connected by springs" as well:
|
|
|
|
// Read more samples
|
|
float uv_mod = 1.0 / float(textureSize(previous_frame, 0).x);
|
|
|
|
float height_up = read_height(previous_frame, UV + vec2(0.0, uv_mod));
|
|
float height_down = read_height(previous_frame, UV + vec2(0.0, -uv_mod));
|
|
float height_left = read_height(previous_frame, UV + vec2(-uv_mod, 0.0));
|
|
float height_right = read_height(previous_frame, UV + vec2(uv_mod, 0.0));
|
|
|
|
// Calculate differences
|
|
float up_delta = spread * (height_up - height_here);
|
|
float down_delta = spread * (height_down - height_here);
|
|
float left_delta = spread * (height_left - height_here);
|
|
float right_delta = spread * (height_right - height_here);
|
|
|
|
// Use the biggest delta to apply to this height
|
|
float sum_delta = max(max(left_delta, right_delta), max(up_delta, down_delta));
|
|
|
|
// Apply velocity and height
|
|
velocity_here += sum_delta + acceleration_here;
|
|
height_here += velocity_here;
|
|
|
|
// Write to the texture
|
|
COLOR = vec4(
|
|
height_here, get_encoded_remainder(height_here),
|
|
velocity_here, get_encoded_remainder(velocity_here)
|
|
);
|
|
} |