//vert
#version 330 core
layout(location = 0) in vec3 vPos;
out vec3 TexCoord1;
out vec4 vPosition;
uniform mat4 ModelViewProjectionMatrix;
void main() {
  TexCoord1 = vPos;
  gl_Position = ModelViewProjectionMatrix * vec4(vPos, 1.0);
  vPosition = gl_Position;
}
//frag
#version 330 core
in vec3 TexCoord1;
out vec4 FragColor;
in vec4 vPosition;
uniform int loops;
uniform float stepSize, sliceSize;
uniform sampler3D intensityVol, gradientVol;
uniform vec3 lightPosition, rayDir;
uniform float ambient = 1.0;
uniform float diffuse = 0.3;
uniform float specular = 0.25;
uniform float shininess = 10.0;
vec3 GetBackPosition (vec3 startPosition) { 
    vec3 invR = 1.0 / rayDir;
    vec3 tbot = invR * (vec3(0.0)-startPosition);
    vec3 ttop = invR * (vec3(1.0)-startPosition);
    vec3 tmax = max(ttop, tbot);
    vec2 t = min(tmax.xx, tmax.yz);
	return startPosition + (rayDir * min(t.x, t.y));
}		
void main() {
	vec3 start = TexCoord1.xyz;
	vec3 backPosition = GetBackPosition(start);
	vec3 dir = backPosition - start;
	float len = length(dir);
	dir = normalize(dir);
	vec4 deltaDir = vec4(dir.xyz * stepSize, stepSize);
	vec4 colorSample,gradSample,colAcc = vec4(0.0,0.0,0.0,0.0);
	float lengthAcc = 0.0;
	float bgNearest = len; //assume no hit
	vec4 prevGrad = vec4(0.0,0.0,0.0,0.0);
	vec4 samplePos;
	samplePos = vec4(start.xyz +deltaDir.xyz* (fract(sin(gl_FragCoord.x * 12.9898 + gl_FragCoord.y * 78.233) * 43758.5453)), 0.0);
	
	//fastPass (len, dir, intensityVol, samplePos);
	if (samplePos.a > len) { //no hit: quit here
		FragColor = colAcc;
		return;		
	}
		vec3 defaultDiffuse = vec3(0.5, 0.5, 0.5);
		
		while (samplePos.a <= len) {
			colorSample = texture(intensityVol,samplePos.xyz);
			if (colorSample.a > colAcc.a)
				colAcc = colorSample+0.00001;
				gradSample= texture(gradientVol,samplePos.xyz);
				samplePos += deltaDir;
		} 
	
	vec4 gradMax = colAcc;
	vec4 ocolAcc = vec4(0.0,0.0,0.0,0.0);
	vec4 prevNorm = vec4(0.0,0.0,0.0,0.0);
	
while (samplePos.a <= len) {
			colorSample = texture(intensityVol,samplePos.xyz);
			if (colorSample.a > colAcc.a)
				colAcc = colorSample+0.00001;
			//	colAcc = colorSample;
			gradSample= texture(gradientVol,samplePos.xyz);
			if (gradSample.a > gradMax.a)
				gradMax = gradSample;
				//colorSample.rgba = texture(intensityOverlay,samplePos.xyz);
			colorSample.a = 1.0-pow((1.0 - colorSample.a), stepSize/sliceSize);
			if (colorSample.a > 0.0) {
				//gradSample = texture(gradientOverlay,samplePos.xyz);
				gradSample.rgb = normalize(gradSample.rgb*2.0 - 1.0);
				if (gradSample.a < prevNorm.a)
					gradSample.rgb = prevNorm.rgb;
				prevNorm = gradSample;
				float lightNormDot = dot(gradSample.rgb, lightPosition);
				vec3 a = colorSample.rgb * ambient;
				vec3 d = max(lightNormDot, 0.0) * colorSample.rgb * diffuse;
				float s =   specular * pow(max(dot(reflect(lightPosition, gradSample.rgb), dir), 0.0), shininess);
				colorSample.rgb = a + d + s;
			}
		colorSample.rgb *= colorSample.a;
		colAcc= (1.0 - colAcc.a) * colorSample + colAcc;
		samplePos += deltaDir;
		lengthAcc += stepSize;
		if ( lengthAcc >= len || colAcc.a > 0.95 )
			break;	
	} 
	colAcc.a = colAcc.a/0.95;
	FragColor = colAcc;
}