//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 		Original 3d depth shader code based off CryTech's 																			//
//		http://www.slideshare.net/TiagoAlexSousa/secrets-of-cryengine-3-graphics-technology											//
//		Special thanks to Jose Negrete AKA BlueSkyDefender for his SuperDepth3D implementation which started me down this path.		//
// 		Contact: sgsrules3dfixes@gmail.com																							//
//																																	//
//																																	//
//																																	//
// UPDATED by Helifax for for Depth Visualisation																					//
// Contact: tavyhome@gmail.com																										//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#version 450

in vec2 texCoord;
layout (location = 0) out vec4 fragColor;

uniform float linearisationMethod;
uniform sampler2D depthTex;

#define farClip 1.0
#define nearClip 0.01

/*
/////////////////////////////////////////////////////////////
PROTOTYPES
/////////////////////////////////////////////////////////////
*/

float GetDepth(vec2 texcoord, float viewMode);
float RawDepth(vec2 texcoord,float viewMode);
float RawDepthInverse(vec2 texcoord,float viewMode);
float LinearizeDepth(vec2 texcoord,float viewMode);
float LinearizeDepthInverse(vec2 texcoord,float viewMode);
float LogarithmicDepth(vec2 texcoord,float viewMode);
float LogarithmicDepthInverse(vec2 texcoord,float viewMode);
vec4 RenderDepthMap();

/*
/////////////////////////////////////////////////////////////
MAIN FUNCTION
/////////////////////////////////////////////////////////////
*/

void main()
{
	fragColor = RenderDepthMap();
}
//-----------------------------------------------------------------------------

float GetDepth(vec2 texcoord, float viewMode)
{
	// Select on how to liniearise the depth!
	if (linearisationMethod == 0.0)
		return RawDepth(texcoord, viewMode);
	else 
	if (linearisationMethod == 1.0)
		return LinearizeDepth(texcoord, viewMode);
	else 
	if (linearisationMethod == 2.0)
		return LogarithmicDepth(texcoord, viewMode);
	else 
	if (linearisationMethod == 3.0)
		return RawDepthInverse(texcoord, viewMode);
	else 
	if (linearisationMethod == 4.0)
		return LinearizeDepthInverse(texcoord, viewMode);
	else 
	if (linearisationMethod == 5.0)
		return LogarithmicDepthInverse(texcoord, viewMode);
}
//-----------------------------------------------------------------------------
float RawDepth(vec2 texcoord,float viewMode)
{
	return texture2D(depthTex, texcoord).x;
}
//-----------------------------------------------------------------------------

float RawDepthInverse(vec2 texcoord,float viewMode)
{
	return 1.0 - RawDepth(texcoord, viewMode);
}
//-----------------------------------------------------------------------------

float LinearizeDepth(vec2 texcoord,float viewMode)
{
	float depth = RawDepth(texcoord, viewMode);
	return 2.0 * nearClip * farClip / (farClip + nearClip - (2.0 * depth - 1.0) * (farClip - nearClip));
}
//-----------------------------------------------------------------------------

float LinearizeDepthInverse(vec2 texcoord,float viewMode)
{
	float depth = RawDepth(texcoord, viewMode);
	return 2.0 * farClip * nearClip / (nearClip + farClip - (2.0 * depth - 1.0) * (nearClip - farClip));
}
//-----------------------------------------------------------------------------

float LogarithmicDepth(vec2 texcoord,float viewMode)
{
	float depth = RawDepth(texcoord, viewMode);
	return (exp (pow (depth, 150 * pow (depth, 55) + 32.75f / pow(depth, 5) - 1850f * (pow ((1 - depth), 2)))) - 1) / (exp (depth) - 1);
}
//-----------------------------------------------------------------------------

float LogarithmicDepthInverse(vec2 texcoord,float viewMode)
{
	float depth = RawDepthInverse(texcoord, viewMode);
	return (exp (pow (depth, 150 * pow (depth, 55) + 32.75f / pow(depth, 5) - 1850f * (pow ((1 - depth), 2)))) - 1) / (exp (depth) - 1);
}
//-----------------------------------------------------------------------------

vec4 RenderDepthMap()
{
	vec4 color = vec4(0);
	float d = GetDepth(texCoord, 0.0);
	color = vec4(d,d,d,1);
	return color;
}
//-----------------------------------------------------------------------------

