precision lowp int;
precision lowp float;

vec3 diff = vec3(0.0);
vec4 albedo = vec4(0.0);
float specVal = 0.0;
vec3 spec = vec3(0.0);
vec3 sss = vec3(0.0);
vec3 fNormal = vec3(0.0);
vec3 fView = vec3(0.0);
float fresnel = 0.0;
float fresnelBase = 0.0;
float rough = 0.0;
vec3 flakeNormal = vec3(0.0);

float curvature = 0.0;

VARYING vec3 vColor;
VARYING vec3 vPos;


vec3 testCol = vec3(0.0);

void MAIN(){
    fNormal = normalize(VAR_WORLD_NORMAL);
    fView=normalize(VIEW_VECTOR);
    fresnelBase = 1.0-max(0.0,dot(fNormal, fView));

    NORMAL  = fNormal;

    fresnel = fresnelBase;
    FRESNEL_POWER = 5.0;
    fresnel = pow(fresnel,FRESNEL_POWER);

    specVal = mix(mix(mix(fresnel*specular,specular,specular),1.0,metalness),1.0,fresnelBase*clearcoat);
    SPECULAR_AMOUNT = specVal;
    albedo = baseColor;
    BASE_COLOR = vec4(1.0);

    vec3 vNormalWsDdx = dFdx(fNormal.xyz);
    vec3 vNormalWsDdy = dFdy(fNormal.xyz);
    float flGeometricRoughnessFactor = pow(clamp(max(dot(vNormalWsDdx, vNormalWsDdx), dot(vNormalWsDdy, vNormalWsDdy)), 0.0, 1.0),0.333);
     METALNESS = mix(metalness,0.0,fresnelBase*clearcoat);
       ROUGHNESS = mix(mix(mix(roughness,0.0,fresnel),0.0,fresnelBase*clearcoat),1.0,flGeometricRoughnessFactor);
    rough = ROUGHNESS;

    curvature = length(fwidth(fNormal));
}


void AMBIENT_LIGHT()
{
    diff += TOTAL_AMBIENT_COLOR;
}

const float PI = 3.141592;
const float e = 2.71828;
float r2 = roughness * roughness;

float sssDepth = 1.0-density;
float sssHalf = sssDepth*0.5;

float PixarBRDF(vec3 normalWS, vec3 lightDirectionWS, vec3 viewDirectionWS) {

    vec3 H = normalize(lightDirectionWS + viewDirectionWS);
    float NH = (dot(normalWS, H));
    NH = NH*(1.0-sssHalf)+sssHalf;
    float NH2 = NH * NH;
    float NH3 = NH2 * NH;
    float VH = (dot(viewDirectionWS, H));
    VH = VH*(1.0-sssHalf)+sssHalf;
    float LN = dot(normalWS, lightDirectionWS);
    LN = LN*(1.0-sssHalf)+sssHalf;
    LN=max(0.0,LN);

    float step1 = NH2 - 1.0;
    float secondStepExp = (step1 / (r2 * NH2));
    float step2 = (pow(e, secondStepExp));
    float step3 = (4.0 * PI * r2 * NH3 * VH);
    float BRDF = max(0.0,step2 / step3) * LN;


    return BRDF;
}


float DisneyDiffuse(vec3 l, vec3 n, vec3 v)
{

    float a = 1.0 - 0.5 * (r2 / (r2 + 0.57));
    float b = 0.45 * (r2 / (r2 + 0.09));

    float nl = dot(n, l);
    nl = nl*(1.0-sssHalf)+sssHalf;
    float nv = (dot(n, v));
    nv = nv*(1.0-sssHalf)+sssHalf;


    float ga = dot(v - n * nv, n - n * nl);

    return max(0.0, nl) * mix(1.0, (a + b * max(0.0, ga) * sqrt((1.0 - nv * nv) * (1.0 - nl * nl)) / max(nl, nv)), roughness);
}

float DICE_SSS(vec3 l, vec3 n, vec3 v){
    vec3 vLTLight = (l+n*sssDistortion);
    float fLTDot = pow(max(dot(v,-vLTLight),0.0),sssPower)*sssScale;
    float flt = 1.0/length(l) * fLTDot * sssDepth;
    return flt;
}

void POINT_LIGHT()
{
    float lightDot = smoothstep(1.0,density,dot(-fNormal, TO_LIGHT_DIR));
    float shadow = mix(SHADOW_CONTRIB,1.0,lightDot*sssDepth);
    diff += LIGHT_COLOR * LIGHT_ATTENUATION * shadow * DisneyDiffuse(TO_LIGHT_DIR, fNormal, fView);
    spec += LIGHT_COLOR * LIGHT_ATTENUATION * shadow * PixarBRDF(fNormal, TO_LIGHT_DIR, fView );
    sss += LIGHT_COLOR * LIGHT_ATTENUATION * shadow * DICE_SSS(TO_LIGHT_DIR, fNormal, fView);
}

void DIRECTIONAL_LIGHT()
{
    float lightDot = smoothstep(1.0,density,dot(-fNormal, TO_LIGHT_DIR));
    float shadow = mix(SHADOW_CONTRIB,1.0,lightDot*sssDepth);
    diff += LIGHT_COLOR * shadow * DisneyDiffuse(TO_LIGHT_DIR, fNormal, fView);
    spec += LIGHT_COLOR * shadow * PixarBRDF(fNormal, TO_LIGHT_DIR, fView );
    sss += LIGHT_COLOR * shadow * DICE_SSS(TO_LIGHT_DIR, fNormal, fView);
}



void POST_PROCESS()
{
    vec3 specularAcc = SPECULAR.rgb+spec;
    vec3 diffuseAcc = albedo.rgb*(DIFFUSE.rgb+diff);
    vec3 totalLight = (mix(diffuseAcc, mix(specularAcc,mix(albedo.rgb*specularAcc,specularAcc+diffuseAcc*fresnel,fresnel),metalness), specVal) +  subsurfaceColor.rgb*(sss)* (1.0-density)*0.5);
    COLOR_SUM = vec4((totalLight+specularAcc*fresnelBase*clearcoat)*vColor.rgb + EMISSIVE, opacity);
}
