#version 430 core

uniform sampler2D diffuse_specular;
uniform sampler2D normal_depth;
uniform sampler2D depth;
uniform vec2 viewport;

uniform mat4 LightMatrix;

/*
 * super ellipse shaping parameters:
 * width, width + edge_width, height, height + edge_height, 2/roundness, -roundness/2
 */
uniform float ellipsoidParams[6];

/*
 * distance shaping parameters:
 * near - near_edge, near, far, far + far_edge
 */
uniform float distanceParams[4];

in vec3 light_pos;
in vec3 light_dir;
in vec3 light_color;

layout (location = 0) out vec4 frag_color;

#include <deferred/gbuffer_read_include.frag>

#include <shading_model/strauss_model_include.frag>


float ellipsoidShape(in vec3 pos)
{
	vec2 abspos = abs(pos.xy / pos.z);

	float w = ellipsoidParams[0];
	float W = ellipsoidParams[1];
	float h = ellipsoidParams[2];
	float H = ellipsoidParams[3];
	float exp1 = ellipsoidParams[4];
	float exp2 = ellipsoidParams[5];

	float inner = w * h * pow(pow(h * abspos.x, exp1) + pow(w * abspos.y, exp1), exp2);
	float outer = W * H * pow(pow(H * abspos.x, exp1) + pow(W * abspos.y, exp1), exp2);

	return 1.0 - smoothstep(inner, outer, 1.0);
}


float distanceShape(in vec3 pos)
{
	float d = abs(pos.x);
	return smoothstep(distanceParams[0], distanceParams[1], d) * (1.0 - smoothstep(distanceParams[2], distanceParams[3], d));
}


void main()
{
	vec2 uv = gl_FragCoord.xy * viewport;
	vec4 ds = texture(diffuse_specular, uv);
	vec4 nd = texture(normal_depth, uv);
	float dpt = texture(depth, uv).x;
	vec4 pos = calc_position(uv, (dpt-0.5)*2.0);

	// calculate attenuation factor
	vec3 lsPos = vec3(LightMatrix * vec4(pos, 1.0));
	float atten = ellipsoidShape(lsPos) * distanceShape(lsPos);

	if ( atten > 0.0 )
	{
		// calculate light model
		vec3 ld = normalize(light_pos - pos);
		vec3 n = normalize(nd.xyz);
		vec3 ed = normalize(-pos);
		vec3 hv = normalize(ld + ed);
		vec3 terms = calculate_strauss_model(n, ld, ed, 0.1, 0.9, 0.0) * atten;

		frag_color.rgb = light_color*ds.rgb*terms.x + light_color*ds.a*(terms.y + terms.z);
		frag_color.a = terms.x;
	}
	else
	{
		frag_color = vec4(0.0);
	}
}

