/* 
 * Copyright (C) 2015  Permutator
 * https://www.shadertoy.com/view/ltfXWS
 *
 * There are a few shaders on this site already that attempt to do this (most notably
 * <https://www.shadertoy.com/view/ldlSzS>), but none of them were quite what I wanted,
 * so I made this one myself.
 * 
 * It has an interface almost as simple as texture2D's, with only one extra parameter
 * for the resolution of the texture. You don't need to pass in the screen resolution
 * or anything, since it uses dFdx and dFdy. I haven't tested this, but it should also
 * work on textures that have been transformed in complex ways, such as ones in 3D
 * environments.
 * It doesn't use fwidth. It uses the Pythagorean Theorem instead. I don't really get
 * why fwidth doesn't just work like that in the first place... Maybe fwidth has some
 * hidden meaning that I don't understand? In any case, it isn't the right function
 * for this.
 * It also has no branching and only calls texture2D once, using the GPU's built-in
 * bilinear interpolation.
 * 
 * You can honestly just lift the v2len and textureBlocky functions out of this shader,
 * put them into your own, and use them. It's very easy.
 * 
 * Since copyright law exists, I guess I ought to put this under a license of some kind
 * if I want you to be able to use it. It's tiny and actually rather self-evident, so
 * I'll put it under the CC0 1.0 Public Domain Dedication:
 * <http://creativecommons.org/publicdomain/zero/1.0/>
 * Ta-dahhh! Now you can use it however you want without even giving me credit.
 */

uniform vec4 OGL2Param;
uniform vec4 OGL2Size;
uniform vec4 OGL2InvSize;
uniform sampler2D OGL2Texture;

vec2 v2len(in vec2 a, in vec2 b) {

    return sqrt(a*a+b*b);
}

vec4 textureBlocky(in sampler2D tex, in vec2 uv, in vec2 res) {

    uv *= res; // enter texel coordinate space.
    
    vec2 seam = floor(uv+.5); // find the nearest seam between texels.
    
    // here's where the magic happens. scale up the distance to the seam so that all
    // interpolation happens in a one-pixel-wide space.

    uv = (uv-seam)/v2len(dFdx(uv),dFdy(uv))+seam;
    
    uv = clamp(uv, seam-.5, seam+.5); // clamp to the center of a texel.
    
    
    return texture2D(tex, uv/res); // convert back to 0..1 coordinate space.
}

vec4 textureUgly(in sampler2D tex, in vec2 uv, in vec2 res) {

    return texture2D(tex, (floor(uv*res)+.5)/res);

}

uniform sampler2D texture;

void main(void){

    //gl_FragColor = textureBlocky( OGL2Texture, gl_TexCoord[0].xy, OGL2Size.xy);
    gl_FragColor = textureUgly( OGL2Texture, gl_TexCoord[0].xy, OGL2Size.xy);

}
