uniform sampler2D tex_entry;
uniform sampler2D tex_exit;
uniform sampler3D tex_intensity;
uniform sampler3D tex_gradient;
uniform sampler1D tex_transfer;
uniform float dz;

varying vec3 normal;
varying vec3 v;
varying vec3 lightvec;
varying mat3 normalMatrix;

void main(){

	vec3 Eye = normalize(-v);
	
	vec4 entry_point = texture2D(tex_entry, vec2(gl_TexCoord[0]));
	
	vec4 Result = {0.0,0.0,0.0,0.0};
	float maxintensity = 0.0;
	
	if (entry_point.w == 0.0) discard;
	else {
		vec4 exit_point = texture2D(tex_exit, vec2(gl_TexCoord[0]));
	
		float dist = distance(entry_point, exit_point)/dz;
		int maxiter = int(floor(dist));
		vec4 diff = (exit_point - entry_point)/dist;
		
		vec4 point = entry_point;
		
		bool work = true;
		int i = 0;

		while(i < maxiter && work){
			vec4 intensity = texture3D(tex_intensity, point.xyz);
			vec4 transferred = texture1D(tex_transfer, intensity.x);
			
			if (intensity.x > (1.0 - transferred.w)){
			
				vec3 normal = normalMatrix * vec3(texture3D(tex_gradient, point.xyz));
				float l_norm = length(normal);
			
				vec3 Reflected = normalize(reflect(-lightvec, normal));
				
				Result.xyz += (1.0 - Result.w) * transferred.w * transferred.xyz;
				Result.w += (1.0 - Result.w) * transferred.w;
				
				vec4 IAmbient        = gl_LightSource[0].ambient;
				vec4 IDiffuse        = gl_LightSource[0].diffuse * max(dot(normal, lightvec), 0.0);
				vec4 ISpecular       = gl_LightSource[0].specular * pow(max(dot(Reflected, Eye), 0.0), 100.0);
				
				Result = vec4(vec3(transferred),1.0);
				
				Result += (IAmbient + IDiffuse + ISpecular)*0.5;
				
				work = false;
				}
			
			i++;
			point += diff;
		}	
		gl_FragColor = Result;
	}
}