#version 120

uniform sampler2D randomMap; // random normalised vectors
uniform sampler2D posMap;    // camera coords before projection
uniform sampler2D normalMap; // contains normal and depth (4th component, in camera coord with projection, linear 0..1)!
uniform sampler2D colorMap;  // colors

uniform mat4 projectionMatrix; // contains GL_PROJECTION_MATRIX

uniform vec3 pSphere[16];

varying vec4 myColor;

#define SAMPLES 16

void main(void)
{
   // these are the random vectors inside a sphere
	/*
   vec3 pSphere[8] = vec3[](
	vec3(0.24710192, 0.6445882, 0.033550154),
	vec3(0.00991752, -0.21947019, 0.7196721),
	vec3(0.25109035, -0.1787317, -0.011580509),
	vec3(-0.08781511, 0.44514698, 0.56647956),
	vec3(-0.011737816, -0.0643377, 0.16030222),
	vec3(0.035941467, 0.04990871, -0.46533614),
	vec3(-0.058801126, 0.7347013, -0.25399926),
	vec3(-0.24799341, -0.022052078, -0.13399573));
	*/

   // get current position in camera coordinates
   vec4 poseye = texture2D(posMap, gl_TexCoord[0].st); 

   //gl_FragColor = texture2D(normalMap, gl_TexCoord[0].st);
   //return;


   // apply AO only to real geometry (asteroids, ships, powerups)
   if(poseye.a < 0){

	   // current normal
	   vec3 normal = texture2D(normalMap, gl_TexCoord[0].st).xyz;

	   // get random vector from texture
	   vec4 vecRanTex = texture2D(randomMap, gl_TexCoord[0].st);
	    
	   vec4 samplePoint; //in camera coord system
	   vec2 sampleTex;   //sample, later in texture coord system
	    
	   // occlusion factor: every sample which is in front of the actual depth will add 1
	   float occlusion = 0.0; 

	   // over all sample random rays (sphere)
	   for(int i=0; i<SAMPLES; i++)
	   {
		  // reflect random vector from sphere with random vector in texture -> "more" random
		   vec4 randomVector = vec4(reflect(pSphere[i], vecRanTex.xyz), 0.0);
         randomVector *= vecRanTex.a; // random scale
		   //vec4 randomVector = vec4(pSphere[i], 0.0);

		  // reflect random vector if im hinteren halbraum
		  if(dot(normalize(randomVector.rgb), normal)<0)
			 randomVector.rgb = reflect(randomVector.rgb, normal);

		  // samplePoint in camera coord
		  samplePoint = (poseye + randomVector);

		  // get texture coordinate of sample vector
		  // let the sample pass through all transformations (pipeline) which every other normal point has done before
		  vec4 clipCoord = projectionMatrix * samplePoint;
		  vec3 normDeviceCoord = clipCoord.xyz / clipCoord.w; //Division durch homog. Koord -> kanon. Volumen -1..1
		  sampleTex.x = ((normDeviceCoord.x+ 1.0)/2.0); //von -1..1 nach 0..1
		  sampleTex.y = ((normDeviceCoord.y+ 1.0)/2.0); 

		  // get depth (in camera coord system before projection) from sample
		  //float sampleDepth = texture2D(normalMap, sampleTex).a; //ehemals
		  vec4 samplePos = texture2D(posMap, sampleTex);
		  float sampleDepth = samplePos.z;

		  if(samplePos.a != -1.0)
			  sampleDepth = -1000.0; //sample pixel without geometry -> far away

		  // get actual depth from sample (in camera coord system before projection)
		  float sampleActualDepth = samplePoint.z;

		  // add sample (slides: green) - sample is in front of depth from texture
		  // be careful: only subtract "same" depths - both must be in the same coord system, here:
		  // camera coord system before projection
		  float diff = sampleActualDepth - sampleDepth;
		  if(diff < 0.0){
			  occlusion += max(0, 1.0 - diff*diff/16.0);
		  }
	   }

	   float strength = 2; //bigger = darker
	   occlusion = strength * occlusion/SAMPLES;

	   // Gewichtungsfunktion 1-x^2 vec3(1.0-pow(occlusion, 2.0));
	   //gl_FragColor.rgba = vec4( 1.0-pow(occlusion, 2.0) );
	   //gl_FragData[0] = texture2D(colorMap, gl_TexCoord[0].st);
	   gl_FragData[0] = vec4( max(0, (1.0 - occlusion)) /*1.0-pow(occlusion, 2.0)*/ );

   } else { //background
	   //gl_FragColor.rgba = vec4(1.0,1.0,1.0, 0.0);
	  // gl_FragData[0] = texture2D(colorMap, gl_TexCoord[0].st);
	   gl_FragData[0] = vec4(-1.0, 0.0, 0.0, 0.0);
   }
      
   //gl_FragColor = texture2D(normalMap, gl_TexCoord[0].st);
   //gl_FragColor = texture2D(posMap, gl_TexCoord[0].st);
   //gl_FragColor = texture2D(colorMap, gl_TexCoord[0].st); 
   //gl_FragColor = texture2D(randomMap, gl_TexCoord[0].st); 
 
}
