
#if !defined shadow_pass
    in vec3 v_normal;
#endif

uniform sampler2DArray u_textures;
uniform ivec4 u_texture_info;
uniform int u_atlas;

#if defined water
    uniform float u_time;
    uniform sampler2D water_normal;
    in vec4 v_position;
#endif

in vec2 v_uv;
in vec4 v_tint;
in vec4 v_highlight;
in vec3 v_fragpos;

layout (location = 0) out vec3 frag_color;

#if !defined shadow_pass && !defined highlight
    layout (location = 1) out vec3 g_normal;
    layout (location = 2) out vec3 g_position;
#endif

#if defined water
    const mat3 TBN = mat3(
            vec3(1.0, 0.0, 0.0),
            vec3(1.0, 0.0, 0.0),
            vec3(0.0, 1.0, 0.0)
    );
    uniform mat4 view_matrix;
#endif

void main() {
    ivec3 texture_size = textureSize(u_textures, 0);
    vec4 col = texture(u_textures, vec3(
        (vec2(u_texture_info.xy) + vec2(u_texture_info.zw) * v_uv) / vec2(texture_size.xy),
        float(u_atlas))
    ) * v_tint;
    if (col.a < 0.3) discard;
    #if defined highlight
        if (all(lessThan(v_highlight.rgb, vec3(0.1)))) discard;
        frag_color = v_highlight.rgb;
    #else
        frag_color = col.rgb;
    #endif
    #if !defined shadow_pass && !defined highlight
        #if defined water
            vec3 base_normal = texture(water_normal, v_position.xz * 1.5 + u_time * 0.001).rgb;
            base_normal = normalize(base_normal * 2.0 - 1.0);
            base_normal = normalize(TBN * base_normal);

            vec3 other_normal = texture(water_normal, v_position.xz * 0.5 + vec2(-u_time * 0.002, u_time * 0.002)).rgb;
            other_normal = normalize(other_normal * 2.0 - 1.0);
            other_normal = normalize(TBN * other_normal);

            vec3 normal = normalize((base_normal + other_normal) * 0.5);
            g_normal = normal * 0.5 + 0.5;

            const vec3 light_dir = normalize(vec3(-1.0, 3.0, 1.0));
            float light = dot(normal, light_dir);
            if (light > 0.95) {
                frag_color.rgb += vec3(light - 0.95) * 20.0;
            }
            g_position = (view_matrix * vec4(v_position.xyz - vec3(normal.x, -normal.y * 0.3, normal.z) * 0.2, 1.0)).xyz;
        #else
            vec3 normal = normalize(v_normal);
            g_normal = normal * 0.5 + 0.5;
            g_position = v_fragpos;
        #endif
    #endif
}
