#version 130

//#extension GL_ARB_gpu_shader_fp64 : enable
//this is needed if double type is used in versions under 400
//which can't be used here coz of too many deprecated features to edit right now
//(need to be done eventually though)


//#define ATTENUATION

// It was expressed that some drivers required this next line to function properly
precision highp float;



uniform float testfactor;
uniform float shininess;//testfactor;//1.5f 0.7f

const int maxnumalights=8;
uniform float widths[maxnumalights];
uniform float heights[maxnumalights];
uniform vec3 pnormals[maxnumalights];
uniform vec3 right[maxnumalights];





#define MAX_LIGHTS 8

#define NUMLIGHTS 4
float actualnumlights;
#define NUMLIGHTSINTEXTURE 4

#define TEXTURESIZE 1024.0f
float SHADOW=0.05f;
#define SHADOWORTHO -0.3f
///the lower the darker














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













//shadow casting spot lights

const int method = 1;
///uniform int method;
// 0 sharp
// 1 smooth
// 2 smooth with linear interpolation

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

in vec4 vpos; //vertex pos
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;
uniform vec3 camPos;


uniform vec4 glColor;
uniform vec4 flash;

uniform float bias;

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

uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform sampler2D lightMap;
///uniform sampler2D specularMap;
//uniform sampler2D shadowMap;
#define shadowMap lightMap
uniform samplerCube envMap;
//uniform float invRadius;
//out vec4 gl_FragColor;

bool inshadow;

/*
float texture2DShadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare){
    vec2 texelSize = vec2(1.0)/size;
    vec2 f = fract(uv*size+0.5);
    vec2 centroidUV = floor(uv*size+0.5)/size;

    float lb = texture2DCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare);
    float lt = texture2DCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare);
    float rb = texture2DCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare);
    float rt = texture2DCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare);
    float a = mix(lb, lt, f.y);
    float b = mix(rb, rt, f.y);
    float c = mix(a, b, f.x);
    return c;
}
*/

in vec4 flashcolor;



vec3 CalcBumpedNormal()
{
    vec3 Normal = N;
    vec3 Tangent = T;
    Tangent = normalize(Tangent - dot(Tangent, Normal) * Normal);
    //vec3 Bitangent = cross(Tangent, Normal);
    vec3 Bitangent = B;
    vec3 BumpMapNormal = 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;
}




vec3 projectOnPlane(in vec3 p, in vec3 pc, in vec3 pn)
{
    float distance = dot(pn, p-pc);
    return p - distance*pn;
}
int sideOfPlane(in vec3 p, in vec3 pc, in vec3 pn){
   if (dot(p-pc,pn)>=0.0) return 1; else return 0;
}
vec3 linePlaneIntersect(in vec3 lp, in vec3 lv, in vec3 pc, in vec3 pn){
   return lp+lv*(dot(pn,pc-lp)/dot(pn,lv));
}

float calculateAttenuation(in int i, in float dist)
{
    /*
    return(1.0 / (gl_LightSource.constantAttenuation +
                  gl_LightSource.linearAttenuation * dist +
                  gl_LightSource.quadraticAttenuation * dist * dist));
    */
    ///return 1.0/dist;
    return clamp(1.0 - lightsinvRadius[i] * sqrt(dist), 0.0, 1.0);
}





void main (void)
{

    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;

    vec3 V=v;
    vec3 N_=CalcBumpedNormal();

    actualnumlights=0.0; for (int i=0;i<NUMLIGHTS;i++) if (lightsOn[i]>0.0) actualnumlights+=1.0;
    SHADOW*=NUMLIGHTS-actualnumlights+1.0;
    if (actualnumlights==1.0) SHADOW=0.6;

    base = texture2D(colorMap, texCoord);

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

    float shadowvalue=SHADOW;
    // if (vpos.y<0.0f) discard;
//    if (renderingmirror>0 && dot(gl_ClipPlane[0], vpos) > 0) {
    if (renderingmirror>0 && dot(clipeq, vpos) < 0)
    {
        discard;
    }
    base = texture2D(colorMap, texCoord);
    vAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
    base = texture2D(colorMap, texCoord);
    //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);


vec4 aambient=vec4(0,0,0,0);
vec4 adiffuse=vec4(0,0,0,0);
vec4 aspecular=vec4(0,0,0,0);

for (int i=0;i<maxnumalights;i++)
    if (lightsEnabled[i]>0.0)
{
/*
    vec3 right = right[i];//normalize(vec3(gl_ModelViewMatrix*gl_LightSource.ambient));
    vec3 pnormal = pnormals[i];//normalize(gl_LightSource.spotDirection);
    vec3 up = normalize(cross(right,pnormal));
*/
    vec3 up = right[i];//normalize(vec3(gl_ModelViewMatrix*gl_LightSource.ambient));
    vec3 pnormal = pnormals[i];//normalize(gl_LightSource.spotDirection);
    vec3 right = normalize(cross(up,pnormal));

    //width and height of the area light:
    float width = widths[i]/2.0;///1.0;
    float height = heights[i]/2.0;///4.0;

    //project onto plane and calculate direction from center to the projection.
    vec3 lightpos;
    lightpos.x=lightsPosx[i];
    lightpos.y=lightsPosy[i];
    lightpos.z=lightsPosz[i];
    vec3 projection = projectOnPlane(V,lightpos,pnormal);// projection in plane
    vec3 dir = projection-lightpos;

    //calculate distance from area:
    vec2 diagonal = vec2(dot(dir,right),dot(dir,up));
    vec2 nearest2D = vec2(clamp(diagonal.x,-width,width),clamp(diagonal.y,-height,height));
    vec3 nearestPointInside = lightpos+(right*nearest2D.x+up*nearest2D.y);

    float dist = distance(V,nearestPointInside);//real distance to area rectangle

    vec3 L = normalize(nearestPointInside - V);
    float attenuation = calculateAttenuation(i, dist);

    ///dm additions:
    ///-------------------------------------------
    attenuation*=clamp(0.3+pow(dot(normalize(nearestPointInside-V),N_),0.3),0.0,1.0);
    /*
    attenuation*=texture2D(specularMap,
                           vec2(
                                i/8.0f+((nearest2D.x+width)/2.0/width)/8.0f,
                                -(nearest2D.y+height)/2.0/height
                                )
                           ).b;
    */
    ///-------------------------------------------

    ///float nDotL = dot(pnormal,-L);
    float nDotL = dot(N_,L);

vec4 colorambient, colordiffuse, colorspecular;
    colorambient.r=0.2;//lightsAmbientr[i];
    colorambient.g=0.2;//lightsAmbientg[i];
    colorambient.b=0.2;//lightsAmbientb[i];
    colorambient.a=1.0;
    colordiffuse.r=lightsDiffuser[i];
    colordiffuse.g=lightsDiffuseg[i];
    colordiffuse.b=lightsDiffuseb[i];
    colordiffuse.a=1.0;
    colorspecular.r=lightsSpecularr[i];
    colorspecular.g=lightsSpecularg[i];
    colorspecular.b=lightsSpecularb[i];
    colorspecular.a=1.0;

    if (nDotL > 0.0 && sideOfPlane(V,lightpos,pnormal) == 1) //looking at the plane
    {
        //shoot a ray to calculate specular:
        //vec3 R = reflect(normalize(-V),N_);
        vec3 R = reflect(normalize(camPos-V),N_);
        vec3 E = linePlaneIntersect(V,R,lightpos,pnormal);

        float specAngle = dot(R,pnormal);
        if (specAngle > 0.0){
	    vec3 dirSpec = E-lightpos;
	    const float scale=1.0;
    	    vec2 dirSpec2D = vec2(dot(dirSpec,right),dot(dirSpec,up));
            vec2 nearestSpec2D = vec2(clamp( dirSpec2D.x,-width,width  ),clamp(  dirSpec2D.y,-height,height))/scale; /// /2.0 is a fix
            ///float dist=length(nearestSpec2D);
            ///shininess=(20.0-clamp(20.0-(dist*20.0),1.0,20.0))/testfactor;
    	    ///float specFactor = 1.0-clamp(length(nearestSpec2D-dirSpec2D)*shininess,0.0,1.0);
            float specFactor = 1.0-clamp(length(nearestSpec2D-dirSpec2D)*shininess,0.0,1.0);
            /*
            float specattenuation=texture2D(specularMap,
                                   vec2(
                                        i/8.0f+1.0/8.0-((nearestSpec2D.x+width)/2.0/width)*scale/8.0f,
                                        -(nearestSpec2D.y+height)/2.0/height*scale
                                        )
                                   ).b;
                                   */
          aspecular += colorspecular * specFactor * specAngle;
        }
        adiffuse  += colordiffuse * attenuation * nDotL;
        ///adiffuse  += colordiffuse * attenuation * nDotL;
        ///adiffuse  += (colordiffuse + vec4(attenuation,attenuation,attenuation,1.0)/128.0) * nDotL;
    }

    ///ambient  += colorambient * attenuation;
	aambient=colorambient;
	//aambient=vec4(0.0,0.0,1.0,1.0);
}

    //gl_FragColor = ( vAmbient*base + accvDiffuse*base + accvSpecular) * att;
    //gl_FragColor = ( vAmbient*base + accvDiffuse*base + accvSpecular);

//float bias = 0.005;
//float bias = 0.005;
//float biasx=bias;
    float totalvisibility=1.0f;
    totalvisibility=0.0f;
    vec4 v1;
    vec2 shadowcoordbig;
    vec4 projectorColor=vec4(0.0f,0.0f,0.0f,1.0f);
//vec4 totalprojectorColor=vec4(1.0f,1.0f,1.0f,1.0f);
    vec4 totalprojectorColor=vec4(0.0f,0.0f,0.0f,1.0f);
    /*
    float r1=1.0f;
    float g1=1.0f;
    float b1=1.0f;
    */
    float depth;
    float ShadowAngle2;
	float totalshadowcount=0.0;
	float visibility = 1.0f;
	vec4 ShadowCoordFull;
    vec4 ShadowCoord2;

    for (int i=0; i<NUMLIGHTS; i++) 
    {
///if (lightsOn[i]>0.0)
if (true)
{	
//for (int i=0;i<1;i++){


        float biasx=bias;
        visibility = 0.0f;
//ShadowAngle2=1.0f-clamp(ShadowAngle[i],0.0f,1.0f);
        ShadowAngle2=ShadowAngle[i];
//if (ShadowAngle<0.25f||ShadowAngle>0.75f) visibility=0.5f+ShadowAngle; else
//if ( texture2D( shadowMap, ShadowCoord.xy ).z  <  ShadowCoord.z-biasx){ //.x should be .z but since we also do coloring in pass1, we can get away with it
        ShadowCoord2=ShadowCoord[i];
        ShadowCoordFull=ShadowCoord[i];
//ShadowCoord2.x-=50.0f;

//if ( texture2D( shadowMap, (ShadowCoord2.xy/ShadowCoord2.w) ).z  <  1.0f-(ShadowCoord2.z/200.0f-0.5f)/ShadowCoord2.w ){


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

        inshadow=false;
        float r=sqrt(x*x+y*y);
        if (i==0) projr=r;
        ///if (r>SPOTR) inshadow=true;// else
        ///if (ShadowAngle2>0.2f){
        if (ShadowAngle2>0.02){
            inshadow=true; //else
            shadowvalue=1.0f;///(1.0f-(ShadowAngle2-0.2f));
            //shadowvalue=0.0f;
        }
        ///if (false)
        {
            //float ShadowAngle3 = dot(normalize(Lights[i].xyz),normalize(vec3(vpos.xyz-LightsPos[i].xzy)));
            float ShadowAngle3 = dot(normalize(N),normalize(vec3(vpos.xyz-LightsPos[i].xyz)));
            if (ShadowAngle3>0.0f)
                inshadow=true;
        }


//ShadowAngle2 = dot(normalize(vN_.xyz),normalize(vec3(vpos.xyz-LightsPos[i].xzy)));
//ShadowAngle2 = dot(normalize(vN_.xyz),normalize(vec3(vpos.xyz-LightsPos[i].xzy)));
//if ((ShadowAngle2)>anglebias) inshadow=true;
//if ((ShadowAngle2)>anglebias) inshadow=true;
//>0.0f
//0.2
//0.1
//0.005

        float smoothsize;
        if (method==0)
            smoothsize=1.0f;
        else
            smoothsize=8.0f; //6.0f 10.0f
        float visibility4=0.0f;
/*
        if (!inshadow)
        {
            vec2 pCoos=vec2(ShadowCoord2.xy/ShadowCoord2.w);
            ///pCoos.y=pCoos.y/2.0f;
            pCoos.y=clamp(pCoos.y,0.01f,0.99f);
            pCoos.x=clamp(pCoos.x,0.01f,0.99f);
            projectorColor=texture2D(lightMap, pCoos);
            projectorColor=vec4(1,0,0,1);

            ///vec4 col=texture2D(specularMap, pCoos);
            ///projectorColor=vec4(vec3((col.r+col.g+col.b)/3.0f),1.0f);
        } else projectorColor=vec4(0,1,0,1);
*/
        ///totalprojectorColor+=projectorColor;

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


                        /*
                        shadowcoordbigU.x=shadowcoordbigD.x=shadowcoordbig.x;
                        shadowcoordbigU.y=shadowcoordbig.y-1.0f/TEXTURESIZE/NUMLIGHTSINTEXTURE;
                        shadowcoordbigD.y=shadowcoordbig.y+1.0f/TEXTURESIZE/NUMLIGHTSINTEXTURE;
                        shadowcoordbigU.z=shadowcoordbig_y-1.0f/TEXTURESIZE;
                        shadowcoordbigD.z=shadowcoordbig_y+1.0f/TEXTURESIZE;

                        shadowcoordbigL.y=shadowcoordbigR.y=shadowcoordbig.y;
                        shadowcoordbigL.z=shadowcoordbigR.z=shadowcoordbig_y;
                        shadowcoordbigL.x=shadowcoordbig.x-1.0f/TEXTURESIZE;
                        shadowcoordbigR.x=shadowcoordbig.x+1.0f/TEXTURESIZE;
                        */

                        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 lcoeff=shadowcoordbigL.x-floor(shadowcoordbigL.x*TEXTURESIZE)/TEXTURESIZE;
                        /*
                        float ulcoeff=abs(shadowcoordbigUR.x-floor(shadowcoordbig.x*TEXTURESIZE)/TEXTURESIZE)*TEXTURESIZE;
                        float urcoeff=abs(shadowcoordbigUL.x-floor(shadowcoordbig.x*TEXTURESIZE)/TEXTURESIZE)*TEXTURESIZE;
                        //float lcoeff=1.0f-rcoeff;
                        float drcoeff=abs(shadowcoordbigDL.z-floor(shadowcoordbig_y*TEXTURESIZE)/TEXTURESIZE)*TEXTURESIZE;
                        float dlcoeff=abs(shadowcoordbigDR.z-floor(shadowcoordbig_y*TEXTURESIZE)/TEXTURESIZE)*TEXTURESIZE;
                        */
                        //float dcoeff=1.0f-ucoeff;
                        float ul,dl,ur,dr;
                        if ( depthUL  <  sc2)
                        {
                            ul=shadowvalue;//SHADOW;
                        }
                        else
                        {
                            ul=1.0f;
                        }
                        if ( depthDL  <  sc2)
                        {
                            dl=shadowvalue;//SHADOW;
                        }
                        else
                        {
                            dl=1.0f;
                        }
                        if ( depthUR  <  sc2)
                        {
                            ur=shadowvalue;//SHADOW;
                        }
                        else
                        {
                            ur=1.0f;
                        }
                        if ( depthDR  <  sc2)
                        {
                            dr=shadowvalue;//SHADOW;
                        }
                        else
                        {
                            dr=1.0f;
                        }
                        //if ( depth  <  sc2) {visibility4+=SHADOW;} else {visibility4+=1.0f;}

                        float fx=fract(shadowcoordbig.x*TEXTURESIZE);
                        float fy=fract(shadowcoordbig_y*TEXTURESIZE);
                        //visibility4/=2.0f;
                        float a=mix(dl,ul,fy);
                        float b=mix(dr,ur,fy);
                        visibility4=mix(a,b,fx);
                    }
                    
//---------------------------------------------------------------
                    else
                    {
                        //if ( depth  <  (ShadowCoord2.z/200.0f) ){
                        if ( depth  <  (ShadowCoord2.z/200.0f-biasx) )
                        {
                            //if ( texture2D( shadowMap, shadowcoordbig ).z  <  (ShadowCoord2.z/200.0f-biasx) ){
                            //if ( texture2D( shadowMap, shadowcoordbig ).z  <  (testz-biasx) ){
                            visibility4 = shadowvalue;//SHADOW;
                        }
                        else
                        {
                            visibility4 = 1.0f;
                        }
                    }
                    //visibility+=visibility4;
                    if (visibility4==shadowvalue)//SHADOW;)
                    {
#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;
            /*
            float attenuation=-depth+(ShadowCoord2.z/200.0f-biasx);
            visibility=attenuation;
            visibility=1.0f-(1.0f-visibility)*attenuation; //dim far shadows
            */
        }

        if (!inshadow)
        {
            vec2 pCoos=vec2(ShadowCoord2.xy/ShadowCoord2.w);
            ///pCoos.y=pCoos.y/2.0f;
            if (pCoos.x<0||pCoos.x>=1.0||pCoos.y<0||pCoos.y>=1.0) projectorColor=vec4(0,0,0,1); else
            {
                pCoos.y=clamp(pCoos.y,0.01f,0.99f);
                pCoos.x=clamp(pCoos.x,0.01f,0.99f);
                projectorColor=texture2D(lightMap, pCoos);
            }
            ///projectorColor=vec4(1,0,0,1);

            ///vec4 col=texture2D(specularMap, pCoos);
            ///projectorColor=vec4(vec3((col.r+col.g+col.b)/3.0f),1.0f);
        } else projectorColor=vec4(0,0,0,1);//projectorColor=vec4(0,1,0,1);
        if (i==0)
            totalprojectorColor=projectorColor;

// 30/180 1/6
//this line was a quick hack to prevent projector wrapping-around, check if it needs correction
        /*
            r1*=ShadowAngle2;
            g1*=ShadowAngle2;
            b1*=ShadowAngle2;//0.5f;
        */
        //v1 = vec4((vec4(r1,g1,b1,1.0f)*visibility).rgb,1.0f);
        //v1= (vec4(1.0f,1.0f,1.ddddddddddddddddddddddddddddddddddddaaaaddddddwwwwwwwssssssssssssssssssssaa0f,1.0f)-((vec4(1.0f,1.0f,1.0f,1.0f)-v1)/1.5f))/1.5f;

//v1 = vec4((vec4(1.0f,1.0f,1.0f,1.0f)*visibility).rgb,1.0f);

        //gl_FragColor = vec4((( vAmbient*base + accvDiffuse*base + accvSpecular) * v1).rgb,1.0f);
        //gl_FragColor = vec4((base * v1).rgb,1.0f)+ accvSpecular;

        //gl_FragColor = vec4((base * v1).rgb,1.0f)+ vec4((accvDiffuse*v1).rgb,1.0f)+vec4(( accvSpecular*v1).rgb,1.0f);

        //if(visibility>0.5f)
        //totalvisibility*=visibility;

		if (false)///shadow caster needs no falloff
        if (!inshadow&&r>=SPOTR-SPOTFALLOFF&&r<=SPOTR) {
            float falloff=(1.0f-float(SHADOW))*(1.0f-(r-(SPOTR-SPOTFALLOFF))/(SPOTFALLOFF))+float(SHADOW);
            //if (float(visibility)>falloff)
                visibility*=float(falloff);
///-if (visibility<SHADOW) visibility=SHADOW;
        }
}
        ///if (lightsOn[i]>1.0){ /// if ortho light
        ///if (i==3){ /// if ortho light
        if (i==3){
			vec4 ShadowCoord2=ShadowCoord[i];
			float visibility4=0.0;
            const float smoothsize2=12.0;
            visibility=0;
            for (float ys=0.0f; ys<smoothsize2; ys++)
                for (float xs=0.0f; xs<smoothsize2; 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;
                    float sc2=(ShadowCoord2.z);
                    ///                testfactor-biasx
                    if ( depth < sc2 / 80.85-0.0096){
                        visibility4 = SHADOWORTHO;
                    } else {
                        visibility4=1.0;
                    }
                    visibility+=1.0f-visibility4;
                }
                visibility/=(smoothsize2*smoothsize2);
                visibility=1.0f-visibility;

            /*
            vec2 shadowcoordbig;
            shadowcoordbig.x=ShadowCoord2.x/ShadowCoord2.w;
            shadowcoordbig.y=(1.0f/NUMLIGHTSINTEXTURE)*3+ShadowCoord2.y/NUMLIGHTSINTEXTURE/ShadowCoord2.w;

            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;
            float sc2=(ShadowCoord2.z);
            if ( depth < sc2 / 80.85-0.0096){
                visibility = SHADOW;///1.0-((1.0-SHADOW)/1.75);
            } else {
                visibility=1.0;
            }
            */
        }

        if (visibility==0.0) visibility=1.0; //if there was no SHADOW nor 1.0 associatated with variable

        totalvisibility+=visibility;

        //if (visibility==1.0f)
        //if (visibility==1.0f)
        //totalprojectorColor+=projectorColor;
        /*
            if (false)
            {
                if (ShadowAngle2<-0.5) totalprojectorColor=vec4(1.0f,0.0f,0.0f,1.0f);
                if (ShadowAngle2<0.0&&ShadowAngle2>-0.5f) totalprojectorColor=vec4(0.0f,1.0f,0.0f,1.0f);
                if (ShadowAngle2>0.0) totalprojectorColor=vec4(0.0f,0.0f,1.0f,1.0f);
                if (ShadowAngle2>0.5) totalprojectorColor=vec4(1.0f,1.0f,1.0f,1.0f);
            }
        */
		totalshadowcount=totalshadowcount+1.0;
    }
	///if (totalshadowcount<1.0) {
       /// totalshadowcount=1.0;
        ///totalvisibility=1.0;
    ///}

    for (int i=int(totalshadowcount);i<NUMLIGHTS;i++){totalvisibility+=1.0;}

    totalvisibility/=NUMLIGHTS;
    ///totalvisibility/=totalshadowcount;


///totalprojectorColor=totalprojectorColor*totalvisibility;


    //r1=g1=b1=1.0f;
    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;
	v1.a=1.0;
    /*
        if (totalvisibility==1.0f)
            gl_FragColor = ( vAmbient*base + accvDiffuse*base + accvSpecular)*v1*glColor+projectorColor;
        else
            gl_FragColor = ( vAmbient*base + accvDiffuse*base + accvSpecular)*v1*glColor;
    */
//debugging:
    /*
    {
            //float ShadowAngle2=ShadowAngle[0];
            //float ShadowAngle2 = dot(normalize(vN_.xyz),normalize(vec3(vpos.xyz-LightsPos[0].xzy)));
            float ShadowAngle2 = dot(normalize(Lights[0].xyz),normalize(vec3(vpos.xyz-LightsPos[0].xyz)));
            if (ShadowAngle2<0.0)
                totalprojectorColor=vec4(0,-ShadowAngle2,0,1);
            else
                totalprojectorColor=vec4(ShadowAngle2,0,0,1);
    }
    */
    ///gl_FragColor = ( vAmbient*base + accvDiffuse*base + accvSpecular)*v1*glColor+totalprojectorColor;
	///aambient=vec4(0.2,0.2,0.2,1.0);
    const float dim=0.50; ///0.65
	///aambient=vec4(0.15,0.25,0.35,1.0)*2.0*dim;
    aambient=vec4(0.3,0.3,0.3,1.0)*2.0*dim;
	///aambient=vec4(1.15,0.18,0.11,1.0)*5.0;
    ///adiffuse*=1.9*dim;
    const float dim2=0.85;
    adiffuse.r=pow(adiffuse.r,1.35)*dim2;
    adiffuse.g=pow(adiffuse.g,1.35)*dim2;
    adiffuse.b=pow(adiffuse.b,1.15)*dim2;//1.55
    ///aambient.b*=1.75;///aambient.b*=2.0;
    base+=vec4(12.0/255.0,1.0/255.0,-1.0/255.0,0.0);
    ///0 16 51 -> 12 17 50


//vec2 pCoos=vec2(ShadowCoord2.xy/ShadowCoord2.w);
//totalprojectorColor=texture2D(lightMap, pCoos);
    const float PFOFF=0.1;
    float pv=projr-(SPOTR-PFOFF); if(pv>0) pv=pow(clamp(1.0-pv/PFOFF,0,1),2.0); else pv=1.0;
    //gl_FragColor = ( aambient*base + adiffuse*base + aspecular)*v1+totalprojectorColor*pv*0.7;//testfactor;
    gl_FragColor = ( aambient*base + adiffuse*base + aspecular);//+totalprojectorColor*pv*0.7;

    vec3 I = normalize(vpos.xyz - camPos);
    vec3 R = reflect(I, -normalize(N_)); /// THIS MINUS HERE IS THE ONLY DIFFERENCE TO THE ORIGINAL SHADER!!!
    vec4 envcol= vec4(texture(envMap, R).rgb, 1.0);
    gl_FragColor+=envcol;
    gl_FragColor/=3.0;
    
    gl_FragColor=envcol;

    gl_FragColor+=flashcolor;

/*
        if (!inshadow)
        {
            vec4 ShadowCoord2=ShadowCoord[0];
            vec2 pCoos=vec2(ShadowCoord2.xy/ShadowCoord2.w);
            ///pCoos.y=pCoos.y/2.0f;
            pCoos.y=clamp(pCoos.y,0.01f,0.99f);
            pCoos.x=clamp(pCoos.x,0.01f,0.99f);
            projectorColor=texture2D(lightMap, pCoos);
            ///projectorColor=vec4(1,0,0,1);

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

    gl_FragColor=projectorColor;
*/

    ///gl_FragColor += flash;

    //gl_FragColor = totalprojectorColor;

    //gl_FragColor = vec4(ShadowAngle2,ShadowAngle2,ShadowAngle2,1.0f);
    //gl_FragColor = texture2D( shadowMap, (ShadowCoord2.xy/ShadowCoord2.w) );
    //gl_FragColor = vec4(vec3(ShadowCoord2.z/200.0f),1.0f);

    /*
    float a=ShadowAngle[2]; //E
    vec4 anglecolor;
    if (a>=0.0) anglecolor=vec4(a,0.0,0.0,1.0);
    if (a<0.0) anglecolor=vec4(0.0,-a,0.0,1.0);
    if (inshadow) anglecolor=vec4(0.0,0.0,1.0,1.0);
    gl_FragColor = anglecolor*v1;
    */
}
