#include "core.fsh"

#ifndef DISL_DISABLE_LIGHT
#include "light.fsh"
#endif

uniform sampler2D texOcc; //sdf texture
uniform sampler2D texUnit; // bitmap texture

uniform vec4 uvSize[32];
uniform vec3 sdfColor[32];
uniform float sdfLevel[32];

in highp vec2 UV_f;
flat in int Idx_f;
in mediump vec3 N_world;

layout(location = 0) out vec4 fragColor;

//debug for lod switch
//#define MIX_DEBUG

vec4 calSDFColor(vec4 Cd_, vec3 lightIntensity, vec2 uv, vec2 dPdx, vec2 dPdy)
{
#if defined(MIX_DEBUG)
    Cd_ *= vec4(vec3(0.0, 0.0, 1.0), 1.0);
#endif
    
    float dist = 0.45 - textureGrad(texOcc, uv, dPdx, dPdy).a; // 0.45 fixed acute angle
    vec2 ddist = vec2(dFdx(dist), dFdy(dist));
    float pixelDist = dist / length(ddist);
    float transparentFactor = clamp(0.5 - pixelDist, 0.0, 1.0);
    return vec4(Cd_.rgb * lightIntensity * transparentFactor, transparentFactor);
}

vec4 calBitMapColor(vec4 Cd_, vec3 lightIntensity, vec2 uv, vec2 dPdx, vec2 dPdy)
{
    float alpha = textureGrad(texUnit, uv, dPdx, dPdy).a;

#if defined(MIX_DEBUG)
    return vec4(vec3(1.0, 0.0, 0.0) * lightIntensity * alpha, alpha);
#endif
    
    return vec4(Cd_.rgb * lightIntensity * alpha, alpha);
}

float calMipMapLevel(vec2 texCoordinate) // in texel units
{
    vec2  dx_vtc        = dFdx(texCoordinate);
    vec2  dy_vtc        = dFdy(texCoordinate);
    float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
    float mml = 0.5 * log2(delta_max_sqr);
    return mml;
}

//no default sdf size
void main()
{

    int Idx = Idx_f;
    float level = sdfLevel[Idx];
    float transLevel = level + 1.0;
    
    vec4 Cd_ = vec4(sdfColor[Idx], 1.0);
    
#if defined(DISL_DISABLE_LIGHT)
    vec3 lightIntensity = vec3(1.0);
#else
    vec3 lightIntensity = CalLightIntensity(N_world, 1.0);
#endif
    
    ivec2 texSize = textureSize(texOcc, 0);
    vec2 uv = uvSize[Idx].xy + fract(UV_f) * uvSize[Idx].zw;
    //use OpenGL ES 3.2 textureQueryLod instead
    
    vec2 localSize = uvSize[Idx].zw * vec2(float(texSize.x), float(texSize.y));
    float lod = calMipMapLevel(UV_f * localSize);
    
    vec2 maxDpUV = uvSize[Idx].zw * localSize;
    vec2 uv2 = uvSize[Idx].xy + UV_f * uvSize[Idx].zw;
    vec2 dPdx = dFdx(uv2);
    vec2 dPdy = dFdy(uv2);
    
    dPdx = min(maxDpUV, dPdx);
    dPdy = min(maxDpUV, dPdy);
    
    vec4 color0 = calSDFColor(Cd_, lightIntensity, uv, dPdx, dPdy);
    vec4 color1 = calBitMapColor(Cd_, lightIntensity, uv, dPdx, dPdy);
    
    if (lod < level) {
        fragColor = color0;
    }
    else if (lod >= level && lod <= transLevel) {
        //float weight = 1.0 / (1.0 + exp(-100.0*((lod-level)-0.95)));
        float weight = lod - level;
        fragColor = vec4(mix(color0, color1, weight));
    }
    else {
        fragColor = color1;
    }
}
