#version 460 compatibility

/*
====================================================================================================

    Copyright (C) 2025 Pyvtron VX Shaders - Pyvtron

    All Rights Reserved unless otherwise explicitly stated.

    Before You Do Something With Pyvtron VX Shaders, You MUST Read This:

    You Must Read The License: https://pyvtron.pages.dev/minecraft-shaders/pyvtron-shaders-license
    And Read The Agreement: https://pyvtron.pages.dev/minecraft-shaders/pyvtron-shaders-agreement

====================================================================================================
*/

#include "/Include/Settings.glsl"

out vec4 texcoord;
out vec4 color;
out vec3 normal;
out vec4 lmcoord;

#if MC_VERSION >= 11500
layout(location = 11) in vec4 mc_Entity;
#else
layout(location = 10) in vec4 mc_Entity;
#endif

uniform vec3 cameraPosition;

uniform mat4 shadowProjectionInverse;
uniform mat4 shadowProjection;
uniform mat4 shadowModelViewInverse;
uniform mat4 shadowModelView;

uniform mat4 dhProjection;

#ifdef DISTANT_HORIZONS
uniform bool dh_is_lod;
#endif

void main() {
    #ifdef DISTANT_HORIZONS
    if (dh_is_lod) {

        gl_Position = ftransform();

        gl_Position = dhProjection * gl_Position;

        float dist = length(gl_Position.xy);
        float dfactor = (1.0 - SHADOW_MAP_BIAS) + dist * SHADOW_MAP_BIAS;
        gl_Position.xy *= 0.95 / dfactor;
        gl_Position.z = mix(gl_Position.z, 0.5, 0.8);
    } else {

        gl_Position = ftransform();

        vec4 position = gl_Position;

        position = shadowProjectionInverse * position;
        position = shadowModelViewInverse * position;

        position.xyz += cameraPosition.xyz;

        if (mc_Entity.x == 8 || mc_Entity.x == 79) {
            position.xyz += 10000.0;
        }

        position.xyz -= cameraPosition.xyz;

        #ifdef SPHERICAL_WORLD
            float d2 = position.x * position.x + position.z * position.z;
            position.y += sqrt(RADIUS * RADIUS - d2) - RADIUS;
        #endif

        position = shadowModelView * position;
        vec4 projected = shadowProjection * position;

        gl_Position = dhProjection * projected;

        float dist = length(gl_Position.xy);
        float dfactor = (1.0 - SHADOW_MAP_BIAS) + dist * SHADOW_MAP_BIAS;
        gl_Position.xy *= 0.95 / dfactor;
        gl_Position.z = mix(gl_Position.z, 0.5, 0.8);
    }
    #else
    gl_Position = ftransform();

    vec4 position = gl_Position;

    position = shadowProjectionInverse * position;
    position = shadowModelViewInverse * position;
    position.xyz += cameraPosition.xyz;

    if (mc_Entity.x == 8 || mc_Entity.x == 79) {
        position.xyz += 10000.0;
    }

    position.xyz -= cameraPosition.xyz;

    #ifdef SPHERICAL_WORLD
        float d2 = position.x * position.x + position.z * position.z;
        position.y += sqrt(RADIUS * RADIUS - d2) - RADIUS;
    #endif

    position = shadowModelView * position;
    vec4 projected = shadowProjection * position;

    gl_Position = dhProjection * projected;

    float dist = length(gl_Position.xy);
    float dfactor = (1.0 - SHADOW_MAP_BIAS) + dist * SHADOW_MAP_BIAS;
    gl_Position.xy *= 0.95 / dfactor;
    gl_Position.z = mix(gl_Position.z, 0.5, 0.8);
    #endif

    vec3 worldNormal = gl_Normal;
    if (mc_Entity.x == 21) {
        worldNormal = vec3(0.0, 1.0, 0.0);
    }
    normal = normalize(gl_NormalMatrix * worldNormal);

    color = gl_Color;

    lmcoord = gl_TextureMatrix[1] * gl_MultiTexCoord1;
    texcoord = gl_MultiTexCoord0;
}
