/********************************************************
    © 2020 Continuum Graphics LLC. All Rights Reserved
 ********************************************************/

#include "/../ContinuumLib/Syntax.glsl"

#define Shadow_glsl -10
#define DynamicShaderStage Shadow_glsl


varying vec2 texcoord;
varying vec2 lightmaps;
varying vec3 worldSpacePosition;
varying vec3 viewSpacePosition;
varying vec4 color;

varying mat3 tbn;
flat varying int blockID;


/***********************************************************************/
#if defined vsh

#include "/../ContinuumLib/Debug.glsl"

attribute vec3 mc_Entity;
attribute vec2 mc_midTexCoord;
attribute vec4 at_tangent;

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

uniform vec3 shadowLightAngles;
uniform vec3 cameraPosition;

uniform float frameTimeCounter;
uniform float shadowAngle;

#include "/../ContinuumLib/Utilities.glsl"

#include "/../ContinuumLib/Uniform/ShadowDistortion.glsl"
#include "/../ContinuumLib/Uniform/ShadowMatrices.glsl"

#include "/../InternalLib/Vertex/VertexDisplacement.vsh"

void main() {
    CalculateShadowMatrices();

    blockID = int(mc_Entity.x);
    texcoord = gl_MultiTexCoord0.xy;
    lightmaps = gl_MultiTexCoord1.xy * (1.0 / 255.0);
	color = gl_Color;

    vec3 normal = gl_NormalMatrix * gl_Normal;
    vec3 tangent = gl_NormalMatrix * (at_tangent.xyz / at_tangent.w);

    tbn = mat3(tangent, cross(tangent, normal), normal);

    /*
    worldSpacePosition = transMAD(shadowModelViewInverse, transMAD(gl_ModelViewMatrix, gl_Vertex.xyz));
    worldSpacePosition = CalculateVertexDisplacement(worldSpacePosition);
    */

    worldSpacePosition = transMAD(shadowModelViewInverse, transMAD(gl_ModelViewMatrix, gl_Vertex.xyz));

    calculateDisplacement(worldSpacePosition, lightmaps.y, blockID);

    viewSpacePosition = transMAD(shadowModelViewCustom, worldSpacePosition);

    vec4 position = viewSpacePosition.xyzz * diagonal4(gl_ProjectionMatrix) + gl_ProjectionMatrix[3];
         position.xy = DistortShadowSpace(position.xy);
         position.z *= 0.25;

    // Ebin
    #ifdef HIDE_PLAYER_SHADOW
        if (   blockID.x == 0 // If the vertex is an entity
            && abs(position.x) < 1.2
            && position.y > -0.1 &&  position.y < 2.2 // Check if the vertex is A bounding box around the player, so that at least non-near entities still cast shadows
            && abs(position.z) < 1.2) {
                color.a = 0.0;
            }
    #endif
	
    gl_Position = position;
}

#endif
/***********************************************************************/



/***********************************************************************/
#if defined fsh

#include "/../ContinuumLib/Debug.glsl"

uniform sampler2D texture;
//uniform sampler2D shadowtex1;

uniform vec3 cameraPosition;
uniform vec3 shadowLightPosition;

uniform mat4 gbufferModelViewInverse;
uniform mat4 shadowModelView;

uniform sampler2D noisetex;

uniform float frameTimeCounter;

#include "/ShaderConstants.glsl"

/* DRAWBUFFERS:01 */
layout (location = 0) out vec4 shadowcolor0;
layout (location = 1) out vec4 shadowcolor1;
#include "/../ContinuumLib/Exit.glsl"

#include "/../ContinuumLib/Utilities.glsl"
#include "/../InternalLib/Fragment/WaterWaves.fsh"

void main() {
    // Leaves fix
    if(!gl_FrontFacing && (blockID == 18 || blockID == 161)) discard;
    
    bool isWater = blockID == 8 || blockID == 9;

    vec4 albedo = texture2D(texture, texcoord) * color;
    vec3 normal = tbn[2];
    if (!isWater && albedo.a < 0.1000003) discard;
    if (isWater) {
        #ifdef WATER_CAUSTICS
            vec3 wavePosition = worldSpacePosition + cameraPosition;
            vec3 normalmap = calculateWaterNormal(wavePosition, 0.0);

            normal = tbn * normalmap;

            vec3 shadowLPos = mat3(shadowModelView) * mat3(gbufferModelViewInverse) * (shadowLightPosition * 0.01);
            
            // Fixed depth
            const float tPlane = 17.5;
            vec3 newViewPos = viewSpacePosition + (refract(shadowLPos, normal, 0.75)) * tPlane;

            float oldArea = length(dFdx(viewSpacePosition)) * length(dFdy(viewSpacePosition));
            float newArea = length(dFdx(newViewPos)) * length(dFdy(newViewPos));

            float caustics = newArea / oldArea * 0.01;
            caustics = pow(caustics, 1.0 / 2.2);

            albedo = vec4(vec3(caustics), 1.0);
        #else
            albedo = vec4(1.0);
        #endif
    }

    //float frontDepth = gl_FragCoord.z;
    //float backDepth = texture2D(shadowtex1, gl_FragCoord.xy * rShadowMapResolution).x;

    bool isTransparent = albedo.a < 1.0;
    float alpha = isTransparent ? (1.0 - pow3(albedo.a)) : 1.0;

    #ifdef WHITE_WORLD
        if (!isWater)
        albedo.rgb = vec3(1.0);
    #endif

    shadowcolor0 = vec4(albedo.rgb * alpha, lightmaps.y * 0.5 + 0.5);

    shadowcolor1 = vec4(normal * 0.5 + 0.5, float(isWater) * 0.5 + 0.5);
    
	exit();
}

#endif
/***********************************************************************/
