#version 120










precision highp float;
#define MAX_LIGHTS 8

#define NUMLIGHTS 4
#define NUMLIGHTSINTEXTURE 4

#define TEXTURESIZE 2048.0f
#define SHADOW 0.3f

vec3 light1 = vec3(0.5,0.5,0.9);
vec3 objdim = vec3(1.66, 0.14, 1.11)*20.0;
vec2 texCoordc;
vec2 uv;

uniform float testvalue;

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];

















int method=2;




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 vec4 vN_;

in vec3 v;
in vec3 N;
in vec3 T;
in vec3 B;

in vec3 originalV;
in vec3 originalN;

uniform vec3 camPos;


uniform vec4 glColor;

uniform float bias;





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

uniform sampler2D shadowMap;




uniform float iTime;

float hash1( float n ) { return fract(sin(n)*43758.5453); }
vec2  hash2( vec2  p ) { p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) ); return fract(sin(p)*43758.5453); }


vec4 voronoi1( in vec2 x, float w )
{
    vec2 n = floor( x );
    vec2 f = fract( x );

	vec4 m = vec4( 8.0, 0.0, 0.0, 0.0 );
    for( int j=-2; j<=2; j++ )
    for( int i=-2; i<=2; i++ )
    {
        vec2 g = vec2( float(i),float(j) );
        vec2 o = hash2( n + g );
		
		
        o = 0.5 + 0.5*sin( iTime*4.0 + 6.2831*o );

        
		float d = length(g - f + o);
		
        
		vec3 col = 0.5 + 0.5*sin(hash1(dot(n+g,vec2(7.0,113.0)))*2.5 + 3.5 + vec3(2.0,3.0,0.0));
        
        col = col*col;
        
        
		float h = smoothstep( 0.0, 1.0, 0.5 + 0.5*(m.x-d)/w );
	    m.x   = mix( m.x,     d, h ) - h*(1.0-h)*w/(1.0+3.0*w); 
		
		m.yzw = mix( m.yzw, vec3(0.5), h ) - h*(1.0-h)*w/(1.0+3.0*w); 
    }
	
	return m;
}

vec4 voronoi2( in vec2 x, float w )
{
    x+=vec2(10000,10000);
    vec2 n = floor( x );
    vec2 f = fract( x );

	vec4 m = vec4( 8.0, 0.0, 0.0, 0.0 );
    for( int j=-2; j<=2; j++ )
    for( int i=-2; i<=2; i++ )
    {
        vec2 g = vec2( float(i),float(j) );
        vec2 o = hash2( n + g );
		
		
        o = 0.5 + 0.5*sin( iTime*4.0*1.15 + 6.2831*o );

        
		float d = length(g - f + o);
		
        
		vec3 col = 0.5 + 0.5*sin(hash1(dot(n+g,vec2(7.0,113.0)))*2.5 + 3.5 + vec3(2.0,3.0,0.0));
        
        col = col*col;
        
        
		float h = smoothstep( 0.0, 1.0, 0.5 + 0.5*(m.x-d)/w );
	    m.x   = mix( m.x,     d, h ) - h*(1.0-h)*w/(1.0+3.0*w); 
		
		m.yzw = mix( m.yzw, vec3(0.5), h ) - h*(1.0-h)*w/(1.0+3.0*w); 
    }
	
	return m;
}

vec3 CalcBumpedNormal()
{
    vec3 Normal = N;
    vec3 Tangent = T;
    Tangent = normalize(Tangent - dot(Tangent, Normal) * Normal);
    
    vec3 Bitangent = B;
    vec3 BumpMapNormal;
    
    if (true)
        
        BumpMapNormal = texture2D(normalMap, uv).xyz;
    else
        BumpMapNormal = texture2D(normalMap, texCoordc).xyz;
    BumpMapNormal = normalize(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 (void)
{
    light1 = vec3(0.5*-1.6,0.5*1.7,0.9);

    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;






    texCoordc.x=(originalV.x/objdim.x+1.0)/2.0;
    texCoordc.y=(originalV.z/objdim.z+1.0)/2.0;

    
    if (true){
            
        vec3 uv2;
        uv2.x=(originalV.x/objdim.z+1.0)/2.0;
        uv2.y=(originalV.y/objdim.z+1.0)/2.0;
        uv2.z=(originalV.z/objdim.z+1.0)/2.0;
        float dx=abs(originalN.x);
        float dy=abs(originalN.y);
        float dz=abs(originalN.z);
        if (dx>=dy&&dx>=dz) {uv=uv2.zy; if (originalN.x<0) uv+=vec2(0.5,0);}
        else if (dy>=dx&&dy>=dz) {uv=uv2.xz;if (originalN.y<0) uv+=vec2(0.5,0);}
        else 
        {uv=uv2.xy; if (originalN.z<0) uv+=vec2(0.5,0);}
        base = texture2D(colorMap, uv);
    }
    else
        base = texture2D(colorMap, texCoordc);






    


    if (renderingmirror>0 && dot(clipeq, vpos) < 0)
    {
        discard;
    }
    
    vAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
    
    
    vAmbient = vec4(1.0f,1.0f,1.0f,1.0f)
               * vec4(lightsAmbientr[0],lightsAmbientg[0],lightsAmbientb[0],1.0f);

    vec3 viewDir = normalize(camPos-v);


    for (int i=0; i<1; i++)
    {
        
        {
            vec3 L = normalize(light1 - v);
            vec3 E = normalize(-v); 
            vec3 R = normalize(-reflect(L,N));
            vec3 lightDir = L;

                vec3 tmpVec = vec3(light1) - v;
	            vec3 alightVec; 
                alightVec.x = dot(tmpVec, T);            
            	alightVec.y = dot(tmpVec, B);
	            alightVec.z = dot(tmpVec, N);
                lightVec=alightVec;
            

            distSqr = dot(lightVec, lightVec);
            
            
            
            att = 1.0 - 0.1f * sqrt(distSqr);
            att*=0.45;
            float att2=att;

            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 *
                       texture2D(lightMap, vec2(diffuse/1.02f,lightMapSelect[i]));

            
            
            diffuse = max(dot(bump,L), 0.0);
            vec4 Idiff = vec4 (lightsDiffuser[i],lightsDiffuseg[i],lightsDiffuseb[i],1.0f)* diffuse*
                        texture2D(lightMap, vec2(diffuse/1.02f,lightMapSelect[i]));
            Idiff = clamp(Idiff, 0.0, 1.0);

            accvDiffuse = accvDiffuse + Idiff *att2;
            

            
            
            

            
            


            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 *
                        texture2D(lightMap, vec2(specular-0.01,lightMapSelect[i]));


            
            
            
            
            
            
            
            
            
            
            vec4 Ispec=vec4(vec3(specular),1.0);
            Ispec = clamp(Ispec, 0.0, 1.0);

            
            accvSpecular = accvSpecular + Ispec * att;

            
            
        }
    }
    
    




    float totalvisibility=1.0f;
    float shadowCount=0.0;
    totalvisibility=0.0f;
    vec4 v1;
    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++) 
    {
        shadowCount+=1.0;



        float biasx=bias;
        float visibility = 1.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);
        
        
        
        



        if (false)
        {
            float ShadowAngle3 = dot(normalize(Lights[i].xyz),normalize(vec3(vpos.xyz-LightsPos[i].xyz)));
            if (ShadowAngle3<0.0)
                inshadow=true;
        }










        float smoothsize;
        if (method==0)
            smoothsize=1.0;
        else
            smoothsize=16.0; 
        float visibility4=0.0f;

        if (inshadow)
        {
            visibility=shadowvalue;
            projectorColor=vec4(0.0f,0.0f,0.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;
visibility4=1.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.0,1.0,1.0,1.0);

        

        totalprojectorColor+=projectorColor;



        

        
        



        
        

        

        
        


        if (!inshadow&&(r>=SPOTR-SPOTFALLOFF&&r<=SPOTR)) {
            float falloff=(1.0f-float(SHADOW))*(1.0f-(r-(SPOTR-SPOTFALLOFF))/(SPOTFALLOFF))+float(SHADOW);
            
                visibility*=float(falloff);
            if (visibility<SHADOW) visibility=SHADOW;
        }

        if (r>=SPOTR-SPOTFALLOFF) { 
            visibility=1.0;
        }
        vec2 pCooCheck=vec2(ShadowCoord2.xy/ShadowCoord2.w);
        if (pCooCheck.x<=0.0||pCooCheck.x>=1.0||pCooCheck.y<=0.0||pCooCheck.y>=1.0) visibility=1.0;


        totalvisibility+=visibility;

        
        
        
        
    }
    
    totalvisibility/=shadowCount;

    totalprojectorColor=totalprojectorColor*totalvisibility;



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

    




    
    bump=CalcBumpedNormal();
    vec3 L = normalize(vec3(-1.1,1.0,-0.9) - v);
    vec3 E = normalize(-v);
    vec3 R = normalize(-reflect(L,N));
    vec3 lightDir = L;
    vec3 reflectDir=reflect(-lightDir,bump);
    const float shininess=1.5f;
    
    accvSpecular = vec4(pow(clamp(dot(viewDir,R)*shininess,0.0,1.0),1.2)); 

    accvDiffuse=vec4(vec3(max(dot(bump,light1),-1.0)),1.0);
    


    
    
 
    
    gl_FragColor = (((vAmbient + accvDiffuse*base + accvSpecular*base)+vec4(0.2*0.75,0.3*0.8,0.55*0.95,1.0)/1.3))*v1;
    gl_FragColor.a = 1.0;

    vec2 p =vec2(vpos.x,vpos.z)*0.015;
    vec4 vor1 = voronoi1( p*5.0, 0.1 );
    vec3 col1 = vec3(pow(sqrt(vor1.x),1.0));
    col1*=pow(vor1.x,3.5);
    vec4 vor2 = voronoi2( p*7.0, 0.1 );
    vec3 col2 = vec3(pow(sqrt(vor2.x),1.0));
    col2*=pow(vor2.x,3.5);
    float col=max(col1.x,col2.x)/9.0;
    
    gl_FragColor += vec4(col,col,col,0.0);

    
    
    
    

    

    
    
    
}
