

#include "/lib/taa/res_params.glsl"
#include "/lib/uniforms.glsl"

#ifdef PBR
varying float shiny;
varying float smoothval;

#ifdef LAB_PBR
uniform sampler2D specular;
#endif
varying vec3 lowresalbedo;
#endif

varying vec4 lmtexcoord;
varying vec4 color;
flat varying float translucent;
flat varying float emissive;

uniform sampler2D texture;
#include "/lib/color_transforms.glsl"
#include "/lib/projections.glsl"
#if defined NORMAL_MAPS
varying mat3 tbnMatrix;
uniform sampler2D normals;

#if defined POM
uniform ivec2 atlasSize;

varying vec4 normalMat2;
varying vec4 tangent;
#include "/lib/pom.glsl"

#endif
#else
varying vec3 normalMat;

#endif
#if defined ENTITY && defined NO_ENTITY_TAA

/* RENDERTARGETS: 0,11,12,3 */
#else
/* RENDERTARGETS: 0,11,12 */

#endif

vec3 normalGenerator(vec2 coord)
{
    float lumaLod = luma(lowresalbedo * color.rgb);
    // coord = mod(coord / 64.0, 1.0);
    float strength = 1.0;
    float deltaPos = 0.000015;

    vec2 offsets[4] = vec2[](vec2(deltaPos, 0.0), vec2(-deltaPos, 0.0), vec2(0.0, deltaPos), vec2(0.0, -deltaPos));

    float heights[4];
    for (int i = 0; i < 4; i++)
    {
        float temp = luma(texture(texture, coord + offsets[i]).rgb);
        heights[i] = 1 - distance(temp, lumaLod);
    }

    float dx = (heights[1] - heights[0]) * strength;
    float dy = (heights[3] - heights[2]) * strength;
    vec3 full = normalize(vec3(dx, dy, 0.5)) + 0.5;

    return full;
}

void main()
{
    vec2 tcoord = lmtexcoord.xy;

/// pom
#ifdef NORMAL_MAPS
#if defined POM
    vec3 fragpos = toScreenSpace((gl_FragCoord.xyz * vec3(texelSize, 1.0)));
    vec3 tangent2 = normalize(cross(tangent.rgb, normalMat2.rgb) * tangent.w);
    mat3 tbnMatrix2 = mat3(tangent.x, tangent2.x, normalMat2.x, tangent.y, tangent2.y, normalMat2.y, tangent.z,
                           tangent2.z, normalMat2.z);
    vec3 p3 = (mat3(gbufferModelViewInverse) * fragpos) + gbufferModelViewInverse[3].xyz;

    tcoord = pomColor(tcoord, fragpos, 0, tbnMatrix2);
    if (readNormal(lmtexcoord.st).a == 1)
        tcoord = lmtexcoord.xy;

#endif
#endif
    ///

    vec4 albedo = texture(texture, tcoord, 0);
    albedo.rgb *= color.rgb;
    float ao = color.a;

    float sss = translucent;

    float emissives = emissive * luma(albedo.rgb) * luma(albedo.rgb);

#ifdef PBR
    float lumaValue = luma(albedo.rgb);
    float lumaLod = luma(lowresalbedo * color.rgb);
    float modifier = clamp(lumaValue / lumaLod, 0.0, 1.0);
    float reflectance = 0.1 * modifier;

    float smoothness = 0.1 * modifier;
    if (shiny > 0)
    {
        reflectance = shiny;
        smoothness = smoothval * modifier;
    }
#ifdef LAB_PBR
    vec4 specularTex = texture(specular, tcoord, 0);

    smoothness = specularTex.x;
    reflectance = specularTex.y;
    sss = specularTex.z;
    emissives = specularTex.w * 255 < 255 ? specularTex.w : 0;

#endif
#endif
#ifdef NORMAL_MAPS
    vec3 normalTex = texture(normals, tcoord, 0).rgb;
    // vec3 normalTex = normalGenerator(lmtexcoord.xy);

    ao *= normalTex.b;
    vec3 normal;

    normal.xy = normalTex.xy * 2.0 - 0.996078431372549;
    normal.z = sqrt(clamp(1.0 - dot(normal.xy, normal.xy), 0.0, 1.0));
    normal = tbnMatrix * normal;
    // normal = tbnMatrix * vec3(0, 0, 1);

#else
    vec3 normal = normalMat;
#endif
    // albedo.rgb = vec3(tcoord, 0);
    albedo.rgb = toLinear(albedo.rgb);

    gl_FragData[0] = albedo; // Albedo

    gl_FragData[1].rgba = vec4(encodeNormal(normal), encodeVec2(lmtexcoord.zw), color.a); // normals

#ifdef PBR
    gl_FragData[2] = vec4(sss, emissives, reflectance, smoothness); // Materials
#else
    gl_FragData[2].rg = vec2(sss, emissives); // Materials
#endif
#ifdef ENTITY
#ifdef NO_ENTITY_TAA


    gl_FragData[3].g = 1; // Materials

#endif
#endif
}
