#version 330 core

uniform sampler3D volume;
uniform sampler1D transfer;
uniform float threshold;
uniform float maxLength;

in vec3 ray_pos;
in vec3 ray_dir;
in vec3 eyeDir;
in vec3 lightDir;

layout (location = 0) out vec4 frag_color;

#include <shading_models/oren_nayar_model_include.frag>

const vec3 voxelSize = vec3(1.0/256.0, 1.0/256.0, 1.0/256.0);

vec3 getNormal(in vec3 at)
{
	const vec3 cellSize = voxelSize; //vec3(1.0/256.0, 1.0/256.0, 1.0/99.0);

	vec3 n = vec3(texture(volume, at - vec3(cellSize.x, 0.0, 0.0)).x - texture(volume, at + vec3(cellSize.x, 0.0, 0.0)).x,
		texture(volume, at - vec3(0.0, cellSize.y, 0.0)).x - texture(volume, at + vec3(0.0, cellSize.y, 0.0)).x,
		texture(volume, at - vec3(0.0, 0.0, cellSize.z)).x - texture(volume, at + vec3(0.0, 0.0, cellSize.z)).x
	);

	return normalize(n);
}

void main()
{
	vec3 ed = normalize(eyeDir);
	vec3 ld = normalize(lightDir);
	vec4 color = vec4(0.0);
	vec3 step = normalize(ray_dir) * voxelSize; //vec3(1.0/256.0, 1.0/256.0, 1.0/99.0);
	vec3 pos = ray_pos;
	for(int i=0; i < 256; i++)
	{
		pos += step;
		// bail out when we're outside the volume
		if ( any(lessThan(pos, vec3(0.0))) || any(greaterThan(pos, vec3(1.0))) )
		{
			break;
		}

		float density = texture(volume, pos).x;

		//vec3 n = getNormal(pos);
		//float lit = max(dot(ld, n), 0.2);

		vec4 t = texture(transfer, threshold + density);
		color.rgb = mix(color.rgb, t.rgb, t.a); //*lit;
		color.a = mix(t.a, 1.0, color.a);
		if ( color.a > 0.95 ) break;
	}

	if ( color.a < 0.1 ) discard;
	//color.a = smoothstep(0.0, threshold, color.a);

	vec3 n = getNormal(pos);
	vec3 terms = calculate_oren_nayar_model(n, ld, ed, 1.0, 8.0);

	frag_color.rgb = color.rgb*terms.x + color.rgb*terms.y + color.rgb*0.1;
	frag_color.a = color.a;
}
