// TSDGLEdgeDistance_Trace.frag
// Blends two distance textures together
#version 100

precision highp float;

uniform sampler2D Texture;
uniform sampler2D Texture2;
uniform int TextureLevels;
uniform float Percent;
uniform float Opacity;
uniform vec4 Color;
uniform vec4 TextureSize;
uniform float DistanceAdjust;

uniform float StrokeWidth;
uniform float StrokeFadeHardnessLeading;
uniform float StrokeFadeHardnessTrailing;

varying vec2 v_TexCoord;

#if MOTION_BLUR
varying vec2 v_Velocity;
#endif

float decodeFloatRGBA(vec4 rgba) {
    return (dot( rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0) ) - 0.5) * 2.0;
}

float decodeTraceRG(vec2 rg) {
    return (rg.r * 255.0 + rg.g * 255.0 * 256.0) / float(TextureLevels);
}

float distanceBilinear()
{
    vec2 texCoord = floor(v_TexCoord * TextureSize.xy) * TextureSize.zw;
    
    float p0q0 = decodeFloatRGBA(texture2D(Texture, texCoord));
    float p1q0 = decodeFloatRGBA(texture2D(Texture, texCoord + vec2(TextureSize.z, 0)));
    float p0q1 = decodeFloatRGBA(texture2D(Texture, texCoord + vec2(0, TextureSize.w)));
    float p1q1 = decodeFloatRGBA(texture2D(Texture, texCoord + vec2(TextureSize.z, TextureSize.w)));
    
    // Bilinear interpolation
    vec2 interpAmount = fract(v_TexCoord * TextureSize.xy);
    vec2 interpQ = mix(vec2(p0q0, p0q1), vec2(p1q0, p1q1), interpAmount.x);
    float result = mix(interpQ.x, interpQ.y, interpAmount.y);
    
    return result;
}

float traceNearest()
{
    vec2 texCoord = floor(v_TexCoord * TextureSize.xy) * TextureSize.zw;
    
    // Nearest neighbor interpolation
    vec2 interpAmount = fract(v_TexCoord * TextureSize.xy);
    interpAmount = floor(interpAmount + vec2(0.5));
    
    float result = decodeTraceRG(texture2D(Texture2, texCoord + interpAmount * TextureSize.zw).xy);
    return result;
}


void main(void)
{
    float trace = traceNearest();
    
    float traceOpacity = 1.0;
    traceOpacity *= clamp((min(2.0*Percent,1.0-1.0/StrokeFadeHardnessLeading) - trace)*StrokeFadeHardnessLeading, 0.0,1.0);
    traceOpacity *= clamp((trace - 2.0*Percent + 1.0)*StrokeFadeHardnessTrailing, 0.0,1.0);
    
    float distOpacity = 0.0;
    if (true || trace > 0.0) {
        float dist = distanceBilinear() * max(TextureSize.x,TextureSize.y);
        //dist += 0.5; // +0.5 to account for AA
        dist *= DistanceAdjust;
        
        distOpacity = dist < 0.0 ? StrokeWidth*0.5 + dist : StrokeWidth*0.5 - dist;
        distOpacity = clamp(distOpacity, 0.0,1.0);
    }
    
    vec4 result = Color * distOpacity * traceOpacity * Opacity;
    
#if 0
    result = mix(vec4(1,0,0,1), vec4(0, vec2(trace), 1), 1.0-result.a);
#endif
    
#if 0
    result = vec4(result.r, trace, traceOpacity, 1);
#endif
    
#if 0
    result = mix(vec4(result.r,0,0,1), vec4(0,traceOpacity,0,1), 0.5) * vec4(1,1,1,1);
#endif
    
#if 0
    result = vec4(distOpacity,0,0,1);
#endif
    
#if 0
    result = vec4(abs(dist/100.0),0,0,1);
#endif
    
#if 0
    result = vec4(v_TexCoord, 0, 1);
#endif
    
    
#if MOTION_BLUR
    gl_FragData[0] = result;
#if MOTION_BLUR_IGNORE_OPACITY
    gl_FragData[1] = vec4(v_Velocity,1,1);
#else
    gl_FragData[1] = (result.a > 0.1 ? 1.0 : 0.0) * vec4(v_Velocity,1,1);
#endif
#else
    gl_FragColor = result;
#endif
    
}
