The main shader:
uniform vec3 mouse;
uniform vec2 resolution;
uniform sampler2D texture;
vec3 computeNormal( vec4 n ) {
// pixel scale
vec2 un = 1.0 / resolution;
vec2 uv = gl_FragCoord.xy / resolution;
// tex sample neighbour-4;
vec3 n_r = texture2D( texture, uv + vec2( 1., 0. ) * un ).xyz;
vec3 n_l = texture2D( texture, uv - vec2( 1., 0. ) * un ).xyz;
vec3 n_u = texture2D( texture, uv + vec2( 0., 1. ) * un ).xyz;
vec3 n_d = texture2D( texture, uv - vec2( 0., 1. ) * un ).xyz;
// partial differences n-4;
vec4 dn = vec4( n.z );
dn -= vec4( n_r.z, n_l.z, n_u.z, n_d.z );
// right - left, up - down;
vec2 xy = vec2( dn.x - dn.y, dn.z - dn.w );
xy += n_r.xy + n_l.xy + n_u.xy + n_d.xy;
xy *= 0.89;
float z = length(xy) * 0.1;
return vec3( xy, z ) * 0.25;
}
void main() {
vec2 uv = gl_FragCoord.xy / resolution;
// normal sampling
vec4 height = texture2D( texture, uv );
float vel = height.a; // previous velocity
float elasticity = 0.002;
float viscosity = 0.06;
vel += - (height.z - 0.01) * elasticity - vel * viscosity;
// compute normal advection
vec3 normal = computeNormal( height );
normal.z += height.z + vel;
float dist = distance( mouse.xy, gl_FragCoord.xy);
float mouseRadius = 10.0;
float peak = 1.9; // max-height
if ( dist <= mouseRadius ) {
float dst = ( mouseRadius - dist ) / mouseRadius;
normal.z += pow( abs(dst), 1.9 ) * peak * 2.5;
normal.xy -= normal.xy * pow( abs(dst), 1.9 ) * 0.1;
normal.z = min( peak, normal.z );
}
gl_FragColor = clamp( vec4( normal, vel ), -1.0, 1.0);
}