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

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 int mode;

float dataRead(vec3 pos)
{
  return texture3D(volume, pos * 0.5 + 0.5).a;
}

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;

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)) * 0.1;

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

  //pos += jitter * 0.05;
  
  vec4 _occlusion = texture2D(occlusion, texCoord * 1.0);
  vec4 _depth = texture2D(depth, texCoord * 1.0);
  
  float previousSample = _occlusion.a;

  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*/);
    
  //voxel = vec4(0,0,0,0.1);
  
  vec4 color = vec4(0);

  //gl_FragColor = vec4(pos, 1.0);
  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)
  {
    //color=vec4(1.0, 0.0, 0.0, 1.0);
    discard;
  }
  else
  {
    //gl_FragColor=vec4(1.0, 0.0, 0.0, 0.1);
   
  //color=vec4(0.0, 0.0, 0.0, 0.0);
	//color = pow(voxel * vec4(previousSample), vec4(0.5));
  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.5)
  {
    color.a = 0.0;
  }
  else
  {
    color.a = 1.0;
  }
  
    
  
    float spacing = 32.0;
    vec3 voxelSize = vec3(1.0 / spacing, 1.0 / spacing, 1.0 / spacing);
    vec3 halfV;
    //vec3 lightPos = vec3(0.0, 2.0, 0.3);  
  
    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));
    //n = vec3(1.0, 0.0, 0.0);
		
		float gm = length(n);
		n = normalize(n);
    
    if (gm < 0.01)
    {
      //color.a = 0.0;
    }

		halfV = normalize(light - pos);
    
    vec3 toFresnel = normalize(view - pos);

		/*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);*/



		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);
    
    //fresnel = (fresnel + _depth.a)* 0.5;
    //piFresnel = fresnel;
   
    //color.rgb = vec3(0.2, 0.0, 0.0);
    color.rgb = vec3(0.8, 0.65, 0.65);

		//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 += pow(1.0 - gm, 5.0);

    color.rgb += vec3(fresnel * 1.0);
    
    
    if (mode == 1)
    {
      color.rgb = vec3(1.0);
      color.b = fresnel;
    }

    //color.a *= pow(gm, 4.0);

    //color.rgb = vec3(0.7);
    //color.rgb *= pow(1.0 - _occlusion.a, 1.0);

    
    //color.rgb = vec3(nDotL, 1.0, nDotL);
    //color.rgb = vec3(0.5, 0.5, 0.5);
    
    //color.a *= 0.1;
  
  
  //color.rgb = vec3(nDotL, 0.3, 0.0);
  //color.rgb = vec3(0.01 * normal.x, 0.0, 0.0);
  //color.a *= (4.0 / normal.y);
  
  //color.a = 1.0 - color.a;
              
  
  
  
  
  //color.rgb = 0.5 + 0.5 * pos;
  //color.rgb = 0.5 + 0.5 * n;
  //color.rgb = vec3(nDotL);
  
  
  
  //color.a = 1.0 - pow(1.0 - color.a, stepSize);
	//color.a *= 0.022;
	//color.rgb = vec3(1.0, 1.0, 0.0);


 //color = mix(color, vec4(1,0,0,0.01), 0.9);

  vec4 _dst = texture2D(dst, texCoord);
  vec4 _src = color; 

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

  gl_FragData[0] = vec4(dstC, dstA);
  //gl_FragData[1] = vec4(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);
  
  vec4 post = projection * modelview * vec4(pos.xyz, 1.0);
  
  float newDepth = (post.z - 0.1) / (16.0 - 0.1);  
 
    //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);
    
  gl_FragData[2] = vec4(vec3(writeDepth), 1.0);
  
      //gl_FragDepth = writeDepth;
      
      //gl_FragDepth = (16.0 - writeDepth) / 16.0;
      
  vec4 eyeSpace = projection * modelview * vec4(pos.xyz, 1.0);
      
  //gl_FragDepth = eyeSpace.z;
  
  if (dstA < 0.1)
  gl_FragDepth = newDepth;
  else
  gl_FragDepth = 1.0;  
 

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