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

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

varying vec3 light;
varying vec3 view;

uniform int mode;

uniform float zClipping;

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(	pos.x, pos.y, pos.z +
  
			0.81 * rand(gl_FragCoord.x * 9999 + gl_FragCoord.y) / zRatio);
      
  vec4 transformed = projection * modelview * vec4(jitter, 1.0);
  transformed /= transformed.w;
  
  jitter.xyz = transformed.xyz;

  

  vec3 jitter2 = vec3(pos);
      
  vec4 transformed2 = projection * modelview * vec4(jitter2, 1.0);
  transformed2 /= transformed2.w;
  
  jitter2.xyz = transformed2.xyz;
  
  
  jitter.xyz -= jitter2.xyz;*/

  //vec4 tJitter =inverse(projection) *  inverse(modelview) * vec4(jitter, 1.0);
  
  //mat4 pmi = projection * modelview;
  
  //vec4 tJitter = pmi * vec4(jitter, 0.0);
  //tJitter /= tJitter.w;
  
  
  
  //jitter = normalize(view) * rand(gl_FragCoord.x * 9999 + gl_FragCoord.y);

  //pos += jitter.xyz;
  
  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);

  if (pos.z / zRatio < zClipping)
  {
    discard;
  }

  //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
  {
    color = voxel;
  }


  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;
      n = vec3(0.0, 0.0, -1.0);
    }*/

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


//  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;
  
  //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[0] = vec4(color.rgb, color.a);
    
    if (color.a < 0.5)
    {
      gl_FragDepth = 1.0;
    }
    else
    {
      gl_FragDepth = gl_FragCoord.z;
    }

}