#extension GL_ARB_texture_rectangle : enable

uniform sampler2DRect u_texture_f;          // value ('fixed' flag at w-component)
uniform sampler2DRect u_texture_gv;         // v-gradient

uniform float u_rez;

/*
p: plus 1
m: minus 1
0: no plus/minus
(exmaples)
f_00 means f(i, j)
f_p0 means f(i+1, j)
*/
vec4 sample_f (vec2 coord) { return texture2DRect(u_texture_f , coord); }
vec4 sample_gv(vec2 coord) { return texture2DRect(u_texture_gv, coord); }

void main() {
    vec2 coord = gl_FragCoord.xy;
    vec2 dx  = vec2(1.0, 0.0);
    vec2 dy  = vec2(0.0, 1.0);
    vec2 dy2 = vec2(0.0, 2.0);
    
    vec4 gv_00 = sample_gv(coord);
    vec4 gv_m0 = sample_gv(coord - dx);
    vec4 gv_p0 = sample_gv(coord + dx);
    vec4 gv_0m = sample_gv(coord - dy);
    vec4 gv_0p = sample_gv(coord + dy);
    
    if (gv_00.w == 1.0) {
        gl_FragColor = gv_00;
        return;
    }
    
    vec4 hv_00 = sample_f(coord + dy) - sample_f(coord);
    vec4 hv_0m = coord.y == 0.5         ? hv_00 : gv_0m.w == 1.0 ? gv_0m : (sample_f(coord          ) - sample_f(coord - dy));
    vec4 hv_0p = coord.y == u_rez - 1.5 ? hv_00 : gv_0p.w == 1.0 ? gv_0p : (sample_f(coord + dy2    ) - sample_f(coord + dy));
    vec4 hv_m0 = coord.x == 0.5         ? hv_00 : gv_m0.w == 1.0 ? gv_m0 : (sample_f(coord + dy - dx) - sample_f(coord - dx));
    vec4 hv_p0 = coord.x == u_rez - 0.5 ? hv_00 : gv_p0.w == 1.0 ? gv_p0 : (sample_f(coord + dy + dx) - sample_f(coord + dx));
    gl_FragColor =
        0.5   * hv_00 +
        0.125 * hv_m0 +
        0.125 * hv_p0 +
        0.125 * hv_0m +
        0.125 * hv_0p;
    gl_FragColor.w = 0.0;
}
