```
#ifdef GL_ARB_gpu_shader5
vec4 coord = vec4(projCoord.xyz / projCoord.www,0.0);
vec4 gather = SHADOWGATHER(tex, coord);
#else
vec4 gather = vec4(0.0);
gather.x = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(0, 0));
gather.y = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(1, 0));
gather.z = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(0, 1));
gather.w = SHADOWCOMPAREOFFSET(tex, projCoord, ivec2(1, 1));
#endif
vec2 f = fract( projCoord.xy * SHADOWMAP_SIZE );
vec2 mx = mix( gather.xz, gather.yw, f.x );
return mix( mx.x, mx.y, f.y );
```

According to the spec (https://www.opengl.org/registry/specs/ARB/texture_gather.txt) and my experiments, textureGather has (0,1),(1,1),(1,0),(0,0) offsets in xyzw, not what is implied above. In particular, it will never make sense to interpolate between xz and yw based on single coordinate, as these values are in corners.