#version 120
#extension GL_EXT_gpu_shader4 : enable









uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform sampler2D lightMap;
uniform sampler2D shadowMap;


#define PI 3.1415926
bool leftside=false;
float fishdx,fishdy;

#define LIGHTING


uniform float iTime;















uniform int actionselector; 
uniform float testvalue;

const float skeyl=1.2;






float fov=65.0;
vec3 rayorigin=vec3(0.0,0.0,0.0);
vec3 raydirection=vec3(0.0,0.0,0.0);
vec3 upvector=vec3(0.0,0.0,0.0);




















#define MAX_LIGHTS 8

#define NUMLIGHTS 4
#define NUMLIGHTSINTEXTURE 4

#define TEXTURESIZE 1024.0f
#define SHADOW 0.3f














uniform float lightsPosx[MAX_LIGHTS];
uniform float lightsPosy[MAX_LIGHTS];
uniform float lightsPosz[MAX_LIGHTS];

uniform float lightsEnabled[MAX_LIGHTS];
uniform float lightsinvRadius[MAX_LIGHTS];
uniform float lightMapSelect[MAX_LIGHTS];


uniform float lightsAmbientr[MAX_LIGHTS];
uniform float lightsAmbientg[MAX_LIGHTS];
uniform float lightsAmbientb[MAX_LIGHTS];

uniform float lightsDiffuser[MAX_LIGHTS];
uniform float lightsDiffuseg[MAX_LIGHTS];
uniform float lightsDiffuseb[MAX_LIGHTS];

uniform float lightsSpecularr[MAX_LIGHTS];
uniform float lightsSpecularg[MAX_LIGHTS];
uniform float lightsSpecularb[MAX_LIGHTS];
















uniform int method;




in vec3 alightVec[MAX_LIGHTS];
in vec3 aeyeVec[MAX_LIGHTS];
in vec2 texCoord;

in vec4 vpos; 
uniform int renderingmirror;
uniform vec4 clipeq;

in float ShadowAngle[NUMLIGHTS];
in vec4 ShadowCoord[NUMLIGHTS];
uniform float anglebias;

uniform vec4 LightsPos[NUMLIGHTS];
uniform vec4 Lights[NUMLIGHTS];
uniform float lightsOn[NUMLIGHTS];


in vec3 v;
in vec3 N;
in vec3 T;
in vec3 B;
uniform vec3 camPos;


uniform vec4 glColor;

uniform float bias;

vec4 v1;
float s;























































































































vec4 lighting_;

vec3 CalcBumpedNormal()
{
    

    vec3 Normal = N;
    vec3 Tangent = T;
    Tangent = normalize(Tangent - dot(Tangent, Normal) * Normal);
    vec3 Bitangent = B;
    
    vec3 BumpMapNormal = normalize(texture2D(normalMap, texCoord).xyz);
    BumpMapNormal = 2.0 * BumpMapNormal - vec3(1.0, 1.0, 1.0);
    vec3 NewNormal;
    mat3 TBN = mat3(Tangent, Bitangent, Normal);
    NewNormal = TBN * BumpMapNormal;
    NewNormal = normalize(NewNormal);
    return NewNormal;
}




void main()
{

 
 
 
 
 


 N=CalcBumpedNormal();
 
 
 

 
 
 
 



 
 
 
 
           
 
 
 
 


    vec3 lightVec;
    vec3 eyeVec;
    vec4 accvDiffuse = vec4(0.0);
    vec4 accvSpecular = vec4(0.0);
    float distSqr;
    vec3 lVec;
    vec3 vVec;
    float att;
    vec4 base;
    vec4 vAmbient;
    vec3 bump;
    float diffuse;
    vec4 vDiffuse;
    vec4 vSpecular;
    float specular;
    vec3 nrmltexture;

    const float SPOTR=0.49f;
    const float SPOTFALLOFF=0.03f;

    float shadowvalue=SHADOW;
    

    if (renderingmirror>0 && dot(clipeq, vpos) < 0)
    {
        discard;
    }
    
    
    base = texture2D(colorMap, texCoord);
    
    vAmbient = vec4(1.0f,1.0f,1.0f,1.0f)
               * vec4(lightsAmbientr[0],lightsAmbientg[0],lightsAmbientb[0],1.0f);

    vec3 viewDir = normalize(camPos-v);



if (true)
{
    for (int i=0; i<5; i++)
    {
        if (lightsEnabled[i]>0.0)
        {
            vec3 L = normalize(vec3(lightsPosx[i],lightsPosy[i],lightsPosz[i]) - v);
            vec3 E = normalize(-v); 
            vec3 R = normalize(-reflect(L,N));
            vec3 lightDir = L;

            lightVec=alightVec[i];
            
            lightVec=L; eyeVec=E; 

            distSqr = dot(lightVec, lightVec);
            float factor=10.0f;
            att = clamp(1.0 - (lightsinvRadius[i]) * sqrt(distSqr), 0.0, 1.0)/factor;


            
            lVec = lightVec * inversesqrt(distSqr);
            

            
            
            bump=CalcBumpedNormal();

            
            diffuse = clamp( dot(lVec, bump), 0.0, 1.0 );
            
            vDiffuse = vec4(lightsDiffuser[i],lightsDiffuseg[i],lightsDiffuseb[i],1.0f) * diffuse;
                       

            
            
            diffuse = max(dot(bump,L), 0.0);
            vec4 Idiff = vec4 (lightsDiffuser[i],lightsDiffuseg[i],lightsDiffuseb[i],1.0f) * diffuse;
                        
            Idiff = clamp(Idiff, 0.0, 1.0);

            accvDiffuse = accvDiffuse + Idiff *att;
            

            
            
            

            
            


            vec3 reflectDir=reflect(-lightDir,bump);
            const float shininess=1.5f;
            
            specular = pow(clamp(dot(viewDir,reflectDir)*shininess,0.0f,1.0f),1.2f); 
            
            
            

            

            vSpecular = vec4(lightsSpecularr[i],lightsSpecularg[i],lightsSpecularb[i],1.0f)* specular;
                        


            
            
            
            
            
            vec4 Ispec = vec4(lightsSpecularr[i],lightsSpecularg[i],lightsSpecularb[i],1.0f) * specular;
                        
            
            
            
            Ispec = clamp(Ispec, 0.0, 1.0);

            
            accvSpecular = accvSpecular + Ispec * att;

            
            
        }
    }
    
    
    lighting_= ( vAmbient + accvDiffuse + accvSpecular)*glColor*base;
    
    




    float totalvisibility=1.0f;
    float shadowCount=0.0;
    totalvisibility=0.0f;
    vec2 shadowcoordbig;
    vec4 projectorColor=vec4(0.0f,0.0f,0.0f,1.0f);

    vec4 totalprojectorColor=vec4(0.0f,0.0f,0.0f,1.0f);
    float depth;
    float ShadowAngle2;
    
    for (int i=0; i<1; i++) 
    {
        //vec4 LightsPos_=LightsPos[i]*testvalue;

        shadowCount+=1.0;



        float biasx=bias*1.4;
        float visibility = 1.0f;
        visibility = 0.0f;

        ShadowAngle2=ShadowAngle[i];


        vec4 ShadowCoord2=ShadowCoord[i];





        float x=0.5f-ShadowCoord2.x/ShadowCoord2.w;
        float y=0.5f-ShadowCoord2.y/ShadowCoord2.w;

        bool inshadow=false;
        float r=sqrt(x*x+y*y);
        //float r_=sqrt(pow((LightsPos[i].x-x),2.0)+pow((LightsPos[i].y-y),2.0));
        bool forcevalue=false;

        if (ShadowAngle2>0.0){
            inshadow=true;
            forcevalue=true;
            //shadowvalue=(1.0f-(ShadowAngle2-0.2f));
        }
        if (false)
        if (ShadowAngle2>0.5){
        //if (-x+0.5<LightsPos[i].x){
            inshadow=false; 
            forcevalue=true;
            //shadowvalue=(1.0f-(ShadowAngle2-0.2f));
        }
        //if (r_>SPOTR*testvalue) inshadow=false;
        if (false){
            float ShadowAngle3 = dot(normalize(Lights[i].xyz),normalize(vec3(vpos.xyz-LightsPos[i].xzy)));
            if (ShadowAngle3<0.0f)
                inshadow=true;
        }
        
        









        float smoothsize;
        if (method==0)
            smoothsize=1.0f;
        else
            smoothsize=4.0f;  //8.0
        float visibility4=0.0f;

        if (forcevalue)
        {
            if (inshadow)
            {
                visibility=shadowvalue;
                projectorColor=vec4(0.0f,0.0f,0.0f,1.0f);
            } else {
                visibility=1.0;
                projectorColor=vec4(1.0f,1.0f,1.0f,1.0f);
            }
        }
        else
        {
            for (float ys=0.0f; ys<smoothsize; ys++)
                for (float xs=0.0f; xs<smoothsize; xs++)
                {

                    shadowcoordbig.x=ShadowCoord2.x/ShadowCoord2.w+xs/TEXTURESIZE;
                    shadowcoordbig.y=(1.0f/NUMLIGHTSINTEXTURE)*i+ShadowCoord2.y/NUMLIGHTSINTEXTURE/ShadowCoord2.w+ys/TEXTURESIZE/NUMLIGHTSINTEXTURE;
                    float shadowcoordbig_y=ShadowCoord2.y/ShadowCoord2.w+ys/TEXTURESIZE;


                    float rdepth=texture2D(shadowMap, shadowcoordbig).r;
                    float gdepth=texture2D(shadowMap, shadowcoordbig).g;
                    float bdepth=texture2D(shadowMap, shadowcoordbig).b;
                    depth=(rdepth*256.0f*256.0f+gdepth*256.0f+bdepth)/65536.0f;

#ifdef ATTENUATION
                    float attenuation=-depth+(ShadowCoord2.z/200.0f-biasx);
#endif

                    if (method==2)
                    {
                        vec3 shadowcoordbigUL;
                        vec3 shadowcoordbigUR;
                        vec3 shadowcoordbigDL;
                        vec3 shadowcoordbigDR;

                        shadowcoordbigUL.x=shadowcoordbigDL.x=shadowcoordbig.x;
                        shadowcoordbigUR.x=shadowcoordbigDR.x=shadowcoordbig.x+1.0f/TEXTURESIZE;

                        shadowcoordbigUL.y=shadowcoordbigUR.y=shadowcoordbig.y+1.0f/TEXTURESIZE/NUMLIGHTSINTEXTURE;
                        shadowcoordbigDL.y=shadowcoordbigDR.y=shadowcoordbig.y;
                        shadowcoordbigUL.z=shadowcoordbigUR.z=shadowcoordbig_y+1.0f/TEXTURESIZE;
                        shadowcoordbigDL.z=shadowcoordbigDR.z=shadowcoordbig_y;


                        rdepth=texture2D(shadowMap, vec2(shadowcoordbigUL.xy)).r;
                        gdepth=texture2D(shadowMap, vec2(shadowcoordbigUL.xy)).g;
                        bdepth=texture2D(shadowMap, vec2(shadowcoordbigUL.xy)).b;
                        float depthUL=(rdepth*256.0f*256.0f+gdepth*256.0f+bdepth)/65536.0f;
                        rdepth=texture2D(shadowMap, vec2(shadowcoordbigUR.xy)).r;
                        gdepth=texture2D(shadowMap, vec2(shadowcoordbigUR.xy)).g;
                        bdepth=texture2D(shadowMap, vec2(shadowcoordbigUR.xy)).b;
                        float depthUR=(rdepth*256.0f*256.0f+gdepth*256.0f+bdepth)/65536.0f;
                        rdepth=texture2D(shadowMap, vec2(shadowcoordbigDL.xy)).r;
                        gdepth=texture2D(shadowMap, vec2(shadowcoordbigDL.xy)).g;
                        bdepth=texture2D(shadowMap, vec2(shadowcoordbigDL.xy)).b;
                        float depthDL=(rdepth*256.0f*256.0f+gdepth*256.0f+bdepth)/65536.0f;
                        rdepth=texture2D(shadowMap, vec2(shadowcoordbigDR.xy)).r;
                        gdepth=texture2D(shadowMap, vec2(shadowcoordbigDR.xy)).g;
                        bdepth=texture2D(shadowMap, vec2(shadowcoordbigDR.xy)).b;
                        float depthDR=(rdepth*256.0f*256.0f+gdepth*256.0f+bdepth)/65536.0f;

                        visibility4=0.0f;
                        float sc2=(ShadowCoord2.z/200.0f-biasx);
                        
                        
                        float ul,dl,ur,dr;
                        if ( depthUL  <  sc2)
                        {
                            ul=shadowvalue;
                        }
                        else
                        {
                            ul=1.0f;
                        }
                        if ( depthDL  <  sc2)
                        {
                            dl=shadowvalue;
                        }
                        else
                        {
                            dl=1.0f;
                        }
                        if ( depthUR  <  sc2)
                        {
                            ur=shadowvalue;
                        }
                        else
                        {
                            ur=1.0f;
                        }
                        if ( depthDR  <  sc2)
                        {
                            dr=shadowvalue;
                        }
                        else
                        {
                            dr=1.0f;
                        }
                        

                        float fx=fract(shadowcoordbig.x*TEXTURESIZE);
                        float fy=fract(shadowcoordbig_y*TEXTURESIZE);
                        
                        float a=mix(dl,ul,fy);
                        float b=mix(dr,ur,fy);
                        visibility4=mix(a,b,fx);
                    }

                    else
                    {
                        
                        if ( depth  <  (ShadowCoord2.z/200.0f-biasx) )
                        {
                            
                            
                            visibility4 = shadowvalue;
                        }
                        else
                        {
                            visibility4 = 1.0f;
                        }
                    }
                    
                    if (visibility4==shadowvalue)
                    {
#ifdef ATTENUATION
                        visibility+=clamp(attenuation*10.0f,0.0f,1.0f);
#else
                        visibility+=1.0f-visibility4;
#endif
                    }
                    else
                        visibility+=0.0f;
                }
            visibility/=(smoothsize*smoothsize);
            visibility=1.0f-visibility;
        }

        if (!inshadow)
        {
            vec2 pCoos=vec2(ShadowCoord2.xy/ShadowCoord2.w);
            pCoos.y=pCoos.y/2.0f;
            pCoos.y=clamp(pCoos.y,0.01f,0.49f);
            pCoos.x=clamp(pCoos.x,0.01f,0.99f);
            

            vec4 col=texture2D(lightMap, pCoos);
            projectorColor=vec4(vec3((col.r+col.g+col.b)/3.0f),1.0f);
            projectorColor=vec4(1.0f);
        }

        totalprojectorColor+=projectorColor;



        
        



        
        

        

        
        

        

        
        
        
        
        
        

        
        //if (r>=SPOTR-SPOTFALLOFF) visibility=1.0;
        //if (r>=testvalue) visibility=1.0;
        totalvisibility+=visibility;
        

        
        
        
    }
    
    
    

    totalprojectorColor=totalprojectorColor*totalvisibility;



    
    totalvisibility=clamp(totalvisibility,0.0f,1.0f);
    v1 = vec4(totalvisibility,totalvisibility,totalvisibility,1.0f);
    

    s=dot(normalize(N),normalize(vec3(vpos.xyz-LightsPos[1].xyz)))*-2.4*0.7;
} else {
    v1=vec4(0.0,0.0,0.0,1.0);
    s=1.0;
    }



    
                        
    
    
    
       
        
        
    
       
    
    
    //gl_FragColor = clamp(( vAmbient*base + accvDiffuse*base + accvSpecular)*clamp((v1*4.0*0.5+0.2),0,1.5)*s*glColor,0.0,1.0);
    //gl_FragColor = lighting_*clamp((v1*4.0*0.5+0.2),0,1.5);
    gl_FragColor = lighting_*clamp((v1*4.0*0.5+0.2),0,1.5)*1.25; 
    //gl_FragColor = vec4(diffuse,diffuse,diffuse,1.0); 
    
    
    
    
    
    




    
    

    

    
    
    
}
