#version 130
#include "commonSettings.glsl"

#define VORONOI_VIEWMODEL_DISTORTION 1 // Enable voronoi viewmodel distortion [0 1]

uniform sampler2D texture;
uniform sampler2D lightmap;

uniform mat4 gbufferModelViewInverse;
uniform vec4 entityColor;
uniform vec3 shadowLightPosition;
uniform vec3 skyColor;
uniform ivec2 atlasSize;
uniform float blindness;
uniform int isEyeInWater;
uniform int heldBlockLightValue;

varying vec4 color;
varying vec3 world;
varying vec3 vert;
varying vec2 coord0;
varying vec2 coord1;
varying float id;

vec2 hash2(vec2 p)
{
    return fract(cos(p*mat2(85.6,-69.3,74.8,-81.2))*475.);
}

vec2 voronoi(vec2 p,vec2 s)
{
    float d = 2.;
    vec2 off = vec2(.5);
    vec2 f = floor(p);

    for(float i = -1.;i<=1.;i++)
    for(float j = -1.;j<=1.;j++)
    {
        vec2 o = (hash2(f+s+vec2(i,j))-.5)+f+.5+vec2(i,j)-p;
        float t = length(o);
        if (d>t)
        {
            d = t;
            off = f+.5+vec2(i,j);
        }
    }
    return off;
}
vec2 off(vec2 p,vec3 s)
{
    return voronoi(p,s.xy+s.yz);
}

/* RENDERTARGETS:0,4 */
void main()
{
    vec3 dir = normalize((gbufferModelViewInverse * vec4(shadowLightPosition,0)).xyz);
    float flip = clamp(dir.y/.1,-1.,1.); dir *= flip;
    vec3 norm = normalize(cross(dFdx(world),dFdy(world)));
    float lambert = dot(norm,dir)*.5+.5;

    float fog = (isEyeInWater>0) ? 1.-exp(-gl_FogFragCoord * gl_Fog.density):
    clamp((gl_FogFragCoord-gl_Fog.start) * gl_Fog.scale, 0., 1.);
    vec3 shad = mix(skyColor*.5+.2,vec3(1),lambert) * texture2D(lightmap,coord1).rgb;

    vec2 res = vec2(textureSize(texture,0));
    vec2 cell = coord0*res;
    vec2 floo = floor(cell);
    vec2 mi = floor(floo/16.)*16.;
    vec2 ma = mi+15.;
    vec3 dif = floor(vert);
    
    // Apply voronoi distortion only if enabled
    #if ENABLE_VORONOI_DISTORTION == 1 && VORONOI_VIEWMODEL_DISTORTION == 1
        vec2 shift = off(cell,dif);
        vec2 off1 = clamp(shift,mi,ma)/res;
    #else
        vec2 off1 = coord0;
    #endif

    vec2 gx = dFdx(coord0);
    vec2 gy = dFdy(coord0);
    vec4 col = textureGrad(texture,off1,gx,gy);
    col.a = min(textureGrad(texture,coord0,gx,gy).a,col.a);
    
    // Store ORIGINAL texture color before any modifications (like gbuffers_textured)
    vec4 originalTexture = col;
    
    // Apply vertex color (biome tinting) - match gbuffers_textured order
    col.rgb *= color.rgb;
    
    // Apply entity color before lighting (match gbuffers_textured order)
    col.rgb = mix(col.rgb, entityColor.rgb, entityColor.a);
    
    // Apply lighting — skip scene shading for glowing held items so they look
    // consistent regardless of environment (dark cave vs bright outdoor)
    #if HANDHELD_LIGHT == 1
        float heldStrength = float(heldBlockLightValue) / 15.0;
        vec3 litCol   = col.rgb * shad * (1.0 - blindness);
        vec3 emissCol = col.rgb; // unlit, pure texture color
        col.rgb = mix(litCol, emissCol, heldStrength);
    #else
        col *= vec4(shad*(1.-blindness),1);
    #endif
    
    // Apply fog
    col.rgb = mix(col.rgb, gl_Fog.color.rgb, fog);
    
    // Store original texture color with vertex color applied (match gbuffers_textured)
    vec4 originalTextureColor = originalTexture * vec4(color.rgb, 1.0);
    
    // Output to multiple buffers (consistent with gbuffers_textured)
    gl_FragData[0] = col; // Final lit color to colortex0
    gl_FragData[1] = vec4(originalTextureColor.rgb, 1.0); // Original color + shadow info to colortex4
}