//#version 330
uniform sampler3D volume;
uniform sampler3D volume2;
uniform float stepSize;

uniform float xfade;
uniform float lfade;

varying vec3 pos;
varying vec3 normal;
varying vec2 texCoord;

varying vec3 light;
varying vec3 view;

uniform sampler2D dst;
uniform sampler2D occlusion;
uniform sampler2D depth;
uniform sampler2D cut;

uniform int useCut;

uniform float level;
uniform float window;

uniform int mode;

uniform float zClipping;

float dataRead(vec3 pos)
{
  vec4 t0 = texture3D(volume, pos * 0.5 + 0.5).a;
  vec4 t1 = texture3D(volume2, pos * 0.5 + 0.5).a;
  
  return mix(t0,t1,xfade);
}

uint wang_hash(uint seed)
{
    seed = (seed ^ 61) ^ (seed >> 16);
    seed *= 9;
    seed = seed ^ (seed >> 4);
    seed *= 0x27d4eb2d;
    seed = seed ^ (seed >> 15);
    return seed;
}

float rand(uint value)
{
	return float(wang_hash(value)) * (1.0 / 4294967296.0);
}

uniform mat4 modelview;
uniform mat4 projection;

uniform float zRatio;



float readDepth(in vec2 coord, in sampler2D depthTexture) {

	//return (texture2D( texture1, coord ).a / (camerarange.y - camerarange.x)); //previous and original
	//return ((texture2D( texture1, coord ).a*ambient_exp) / (camerarange.y - camerarange.x)); //previous and original
	//return (texture2D( texture1, coord ).a*100000.0)/2000.0f;
	float n = 0.1; // camera z near
	float f = 16.0; // camera z far
	float z = texture2D(depthTexture, coord).x;
	return (2.0 * n) / (f + n - z * (f - n));	
	//return (texture2D( texture0, coord ).x*10.0)/15.0;
}

float readDepthRaw(in vec2 coord, in sampler2D depthTexture)
{
  return texture2D(depthTexture, coord).r;
}

float encodeDepth( in float depth )
{
	float n = 0.1; // camera z near
	float f = 16.0; // camera z far
	float z = depth;
	return (2.0 * n) / (f + n - z * (f - n));	
}



void main(){
  pos.z *= zRatio;
  //pos *= 0.7;

  //vec3 jitter = view * 0.0007 * rand(gl_FragCoord.x * 9999 + gl_FragCoord.y);
  vec3 jitter = vec3(	0.0,
			0.0,
			rand(gl_FragCoord.x * 9999 + gl_FragCoord.y));

  jitter = (vec4(jitter, 1.0) * modelview).xyz;
  
  //jitter = normalize(view) * rand(gl_FragCoord.x * 9999 + gl_FragCoord.y);

  pos += jitter * 0.01;
  
  vec4 _occlusion = texture2D(occlusion, texCoord * 1.0);
  vec4 __depth = texture2D(depth, texCoord * 1.0);
  //float __depth = readDepth(texCoord);
  
  float _cutDepth = readDepthRaw(texCoord, cut);  
  
  float previousSample = _occlusion.a;


  pos.y = -pos.y;
  pos.x = -pos.x;

  vec4 voxel = texture3D(volume, pos * 0.5 + 0.5
		/*vec3(	rand(gl_FragCoord.x * 9999 + gl_FragCoord.y),
			rand(gl_FragCoord.x * 9999 + gl_FragCoord.y),
			rand(gl_FragCoord.x * 9999 + gl_FragCoord.y)
		) * 0.005*/);

  vec4 voxel2 = texture3D(volume2, pos * 0.5 + 0.5
		/*vec3(	rand(gl_FragCoord.x * 9999 + gl_FragCoord.y),
			rand(gl_FragCoord.x * 9999 + gl_FragCoord.y),
			rand(gl_FragCoord.x * 9999 + gl_FragCoord.y)
		) * 0.005*/);
  
  
   
  voxel = mix(voxel, voxel2, xfade);
    
  vec4 color = vec4(0);

  if (pos.z / zRatio < zClipping)
  {
    discard;
  }
  
  if (pos.x < -1.0 || pos.x > 1.0 ||
      pos.y < -1.0 || pos.y > 1.0 ||
      pos.z < -1.0 || pos.z > 1.0)
  {
    discard;
  }
  else
  {
    color = voxel;
  }
  
  
  /*float _x0 = 0.40;
  float _x1 = 0.50;
  
  if (color.a <= _x0)
  {
    color.a = 0.0;
  }
  else if (color.a >= _x1)
  {
    color.a = 1.0;
  }
  else
  {
    color.a = (color.a - _x0) / (_x1 - _x0);
  }*/


 /* if (color.a < 0.01)
  {
    color.a = 0.0;
  }
  else
  {
    color.a = 1.0;
  }      */
  
  if (color.a > 0.0 && color.a < 1.0)     
    color.a = 1.0 - pow(1.0 - color.a, length(-1.0 + 2.0 * __depth.xyz - pos.xyz));

  color.a = clamp(pow(color.a, 1.0) * 20.0, 0.0, 1.0);
       
       
  color.a =        
       mix(
					step(level + window / 2.0, color.a),
					step(level - window / 2.0, color.a),
					(color.a - (level - window / 2.0)) / window
				);    
       
     
  //color.rgb = vec3(0.8, 0.65, 0.65);
  color.rgb = vec3(0.3, 0.5, 1.0);
   
   
 
         if (lfade > 0.0)
         {
    float spacing = 32.0;
    vec3 voxelSize = vec3(1.0 / spacing, 1.0 / spacing, 1.0 / spacing);
    vec3 halfV;
 
    vec3 n;
  
    n.x = dataRead(pos - vec3(voxelSize.x, 0.0, 0.0)) - dataRead(pos + vec3(voxelSize.x, 0.0, 0.0));
		n.y = dataRead(pos - vec3(0.0, voxelSize.y, 0.0)) - dataRead(pos + vec3(0.0, voxelSize.y, 0.0));
		n.z = dataRead(pos - vec3(0.0, 0.0, voxelSize.z)) - dataRead(pos + vec3(0.0, 0.0, voxelSize.z));
		
		float gm = length(n);
		n = normalize(n);
  
		halfV = normalize(light - pos);    
    vec3 toFresnel = normalize(view - pos);
		float nDotL = max(dot(n, halfV), 0.0);
    float fresnel = pow(max(dot(n, toFresnel), 0.0), 0.5);
    fresnel = clamp(pow(1.0 - fresnel, 1.0), 0.0, 1.0);
     
     vec3 originalRGB = color.rgb;
    
		//diffuse
    color.rgb = mix(vec3(0.0, 0.02, 0.1), color, max(0.1, nDotL));
    color.rgb = mix(vec3(0.0, 0.02, 0.15), color, max(0.1, nDotL));
		//specular
		color.rgb = mix(color.rgb, vec3(1.0, 1.0, 1.0), clamp(pow(nDotL, 160.0) * 1.7, 0.0, 1.0));
    
    color.rgb = mix(originalRGB, color.rgb, lfade);

    //color.rgb += pow(1.0 - gm, 5.0);
    //color.rgb += vec3(fresnel * 1.0);


    //ao
		/*vec4 s = vec4(0);

		float t;
		for (t = 0.01; t < 0.25; t += 0.005)
		{
			s += dataRead(pos + halfV * t) * (0.25 - t) * 3.5;
		}
		s /= 1.3;
		s = clamp(s, 0.0, 1.0);*/
    
    
    //color.rgb *= s;
    
    //color.a *= pow(gm, 5.0);




                     }
                              
   // color.rgb *= pow(1.0 - _occlusion.a, 1.0);
   
   
   color.rgb = mix(color.rgb * pow(1.0 - _occlusion.a, 1.0), color.rgb, lfade);
    
    

  vec3 posCorrected = pos.xyz;
  posCorrected.z /= zRatio;
  
  vec4 post = projection * modelview * vec4(posCorrected.xyz, 1.0);
  
  float ndcDepth = post.z / post.w;
  float rd = ((gl_DepthRange.diff * ndcDepth) + gl_DepthRange.near + gl_DepthRange.far) / 2.0;
  
  //cut by depth
  if (useCut == 1 && _cutDepth < rd) color.a = 0.0;
  
  //color.rgba = vec4(vec3(_cutDepth), 1.0);


  vec4 _dst = texture2D(dst, texCoord);
  vec4 _src = color;
  
  /*vec3 dstC = (1.0 - _dst.a) * _dst.rgb + _src.rgb * _dst.a;
  float dstA = (1.0 - _dst.a) * _dst.a;*/
  
  //under
  vec3 dstC = _dst.a * (_src.a * _src.rgb) + _dst.rgb;
  float dstA = 0.0 + (1.0 - _src.a) * _dst.a;
    
  //dstC = vec3(_dst.rgb);

  //over
  /*vec3 dstC = _src.rgb * _src.a + (1.0 - _src.a) * _dst.rgb;
  float dstA = _src.a * (1.0 - _src.a);*/

  gl_FragData[0] = vec4(dstC,dstA);
  gl_FragData[1] = vec4(0,0,0, clamp((_occlusion.a + (1.0 - dstA) * 0.2), 0.0, 1.0));
  //gl_FragData[1] = vec4(vec3(_occlusion.a + (1.0 - dstA) * 0.05), 1.0);

  
  //gl_FragData[1] = vec4(1.0, 1.0, 1.0, voxel.a);
  
  
  
  float ndc_depth = post.z / post.w;
  
  float far = 1.0;
  float near = 0.0;
  float dddepth = (((far-near) * ndc_depth) + near + far) / 2.0;
  float newDepth = dddepth;
  
  
  
  newDepth = 0.5*(post.z / post.w)+0.5;
  //newDepth = 0.5;
  
  //float newDepth = post.z / post.w;
  
  //float newDepth = (post.z / post.w - 0.1) / (16.0 - 0.1);
    
  
  //float newDepth = post.z;
 
    //float A = projection[2].z;
    //float B = projection[3].z;
    //newDepth = 0.5*(-A*newDepth + B) / newDepth + 0.5;    
      
  float writeDepth = __depth.r;
  
  if (dstA < 1)
    writeDepth = min(__depth.r, newDepth);
    
  //writeDepth = 0;
    
  gl_FragData[2] = vec4(0.5 + 0.5 * pos.xyz, vec3(writeDepth));
  
      //gl_FragDepth = 0.0;
      
      //gl_FragDepth = (16.0 - writeDepth) / 16.0;
      
   
  //gl_FragDepth = eyeSpace.z;
  
    /*
  vec4 hp = projection * modelview * vec4(pos.xyz, 1.0);
    
  if (_src.a > 0.0)
  {
    gl_FragDepth = (0.5*(hp.z / hp.w)+0.5);
    //gl_FragData[2] = vec4(vec3(newDepth), 1.0);
  }
  else
  {
    gl_FragDepth = 1.0;
    //gl_FragData[2] = vec4(vec3(1.0), 1.0);
  } 
      */

  //gl_FragColor = vec4(dstC, dstA);
  
  //gl_FragColor=vec4(0.0, 1.0, 0.0, 0.1);
}