/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkShaders.h
	Version:		$Revision: 2876 $
	Date:			$Date: 2012-04-01 15:25:38 +0200 (So, 01 Apr 2012) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/

#ifndef SHADERS_H__
#define SHADERS_H___

namespace ritk
{

/**	@ingroup	Visualization
 *	@author		Jakob Wasza
 *	@brief		Fragement shader for RImages
 *
 *	@details
 *	This fragment shader is supposed to be used with the OpenGLRImageEntity class.
 *	Its purposes are to \n
 *		-	blend RGB texture and range information via a LUT \n
 *		-	per-pixel based high-peformance lighting \n
 *	Note, that instead of the range information any scalar-valued image can be used. \n
 *	Note, that this shader is supposed to be used with the OpenGLRImageEntity_VertexShader
 */
/*
			if ( m_EnableTriangeTextureInterpolation )																														\
			{																																								\
				PrimaryColor = PrimaryVertexColor;																														\
			}																																								\
			else																																							\
			{																																								\
				PrimaryColor = texture2D(m_PrimaryPayloadTexture, gl_TexCoord[0].st);																					\
			}																																								\
			vec4 PrimaryColor = texture2D(m_PrimaryPayloadTexture, gl_TexCoord[0].st);																					\
*/	


const char *OpenGLRImageEntity_FragementShader = "																															\
	uniform bool m_DiscardInvalidFragments;																																	\
																																											\
	uniform bool m_PrimaryPayloadClampEnabled;																																\
	uniform vec3 m_PrimaryPayloadClampMin;																																	\
	uniform vec3 m_PrimaryPayloadClampMax;																																	\
	uniform bool m_PrimaryPayloadUseLUT;																																	\
	uniform sampler2D m_PrimaryPayloadTexture;																																\
	uniform sampler1D m_PrimaryPayloadLUTTexture;																															\
																																											\
	uniform bool m_SecondaryPayloadClampEnabled;																															\
	uniform vec3 m_SecondaryPayloadClampMin;																																\
	uniform vec3 m_SecondaryPayloadClampMax;																																\
	uniform bool m_SecondaryPayloadUseLUT;																																	\
	uniform sampler2D m_SecondaryPayloadTexture;																															\
	uniform sampler1D m_SecondaryPayloadLUTTexture;																															\
																																											\
	uniform bool m_EnableLighting;																																			\
	uniform bool m_EnableTriangleTextureInterpolation;																														\
																																											\
	uniform sampler2D m_FlagTexture;																																		\
																																											\
	uniform float m_Alpha;																																					\
																																											\
	varying float ValidFlag;																																				\
	varying vec3 Normal;																																					\
	varying vec3 VertexCoord;																																				\
	varying vec3 LightVec;																																					\
	varying vec4 PrimaryVertexColor;																																		\
	varying vec4 SecondaryVertexColor;																																		\
																																											\
	void main()																																								\
	{																																										\
		int Flag = (int)(255*texture2D(m_FlagTexture, gl_TexCoord[0].st).r);																								\
		ValidFlag = Flag&0x00000001;																																		\
		if ( m_DiscardInvalidFragments && abs(ValidFlag-1) > 1e-6 )																											\
		{																																									\
			discard;																																						\
		}						 																																			\
		else																																								\
		{																																									\
			vec4 PrimaryColor = PrimaryVertexColor;																															\
																																											\
			if ( ! m_EnableTriangleTextureInterpolation )																													\
			{																																								\
				PrimaryColor = texture2D(m_PrimaryPayloadTexture, gl_TexCoord[0].st);																						\
			}																																								\
																																											\
			if ( m_PrimaryPayloadClampEnabled )																																\
			{																																								\
				PrimaryColor[0] = clamp(PrimaryColor[0], m_PrimaryPayloadClampMin[0], m_PrimaryPayloadClampMax[0]);															\
				PrimaryColor[1] = clamp(PrimaryColor[1], m_PrimaryPayloadClampMin[1], m_PrimaryPayloadClampMax[1]);															\
				PrimaryColor[2] = clamp(PrimaryColor[2], m_PrimaryPayloadClampMin[2], m_PrimaryPayloadClampMax[2]);															\
				PrimaryColor[0] = (PrimaryColor[0] - m_PrimaryPayloadClampMin[0])/(m_PrimaryPayloadClampMax[0]-m_PrimaryPayloadClampMin[0]);								\
				PrimaryColor[1] = (PrimaryColor[1] - m_PrimaryPayloadClampMin[1])/(m_PrimaryPayloadClampMax[1]-m_PrimaryPayloadClampMin[1]);								\
				PrimaryColor[2] = (PrimaryColor[2] - m_PrimaryPayloadClampMin[2])/(m_PrimaryPayloadClampMax[2]-m_PrimaryPayloadClampMin[2]);								\
			}																																								\
																																											\
																																											\
			if ( m_PrimaryPayloadUseLUT )																																	\
			{																																								\
				PrimaryColor = texture1D(m_PrimaryPayloadLUTTexture, (PrimaryColor.r + PrimaryColor.g + PrimaryColor.b)/3.0);												\
			}																																								\
																																											\
			vec4 SecondaryColor = SecondaryVertexColor;																														\
																																											\
			if ( ! m_EnableTriangleTextureInterpolation )																													\
			{																																								\
				SecondaryColor = texture2D(m_SecondaryPayloadTexture, gl_TexCoord[0].st);																					\
			}																																								\
			if ( m_SecondaryPayloadClampEnabled )																															\
			{																																								\
				SecondaryColor[0] = clamp(SecondaryColor[0], m_SecondaryPayloadClampMin[0], m_SecondaryPayloadClampMax[0]);													\
				SecondaryColor[1] = clamp(SecondaryColor[1], m_SecondaryPayloadClampMin[1], m_SecondaryPayloadClampMax[1]);													\
				SecondaryColor[2] = clamp(SecondaryColor[2], m_SecondaryPayloadClampMin[2], m_SecondaryPayloadClampMax[2]);													\
				SecondaryColor[0] = (SecondaryColor[0] - m_SecondaryPayloadClampMin[0])/(m_SecondaryPayloadClampMax[0]-m_SecondaryPayloadClampMin[0]);						\
				SecondaryColor[1] = (SecondaryColor[1] - m_SecondaryPayloadClampMin[1])/(m_SecondaryPayloadClampMax[1]-m_SecondaryPayloadClampMin[1]);						\
				SecondaryColor[2] = (SecondaryColor[2] - m_SecondaryPayloadClampMin[2])/(m_SecondaryPayloadClampMax[2]-m_SecondaryPayloadClampMin[2]);						\
			}																																								\
			if ( m_SecondaryPayloadUseLUT )																																	\
			{																																								\
				SecondaryColor = texture1D(m_SecondaryPayloadLUTTexture, (SecondaryColor.r + SecondaryColor.g + SecondaryColor.b)/3.0);										\
			}																																								\
																																											\
			vec4 RawColor = (1.0-m_Alpha)*PrimaryColor + m_Alpha*SecondaryColor;																							\
																																											\
			if ( m_EnableLighting )																																			\
			{																																								\
				vec3 Eye = normalize(-VertexCoord);																															\
				vec3 Reflected = normalize(reflect(-LightVec, Normal));																										\
				vec4 IAmbient = gl_LightSource[0].ambient;																													\
				vec4 IDiffuse = gl_LightSource[0].diffuse * max(dot(Normal,LightVec), 0.0);																					\
				vec4 ISpecular = gl_LightSource[0].specular * max(dot(Reflected, Eye), 0.0);																				\
																																											\
				gl_FragColor = 0.6f* RawColor;																																\
				gl_FragColor += 0.2f * IDiffuse;																															\
				gl_FragColor += 0.1f * ISpecular;																															\
				gl_FragColor += 0.1f * IAmbient;																															\
			}																																								\
			else																																							\
			{																																								\
				gl_FragColor = RawColor;																																	\
			}																																								\
		}																																									\
	}																																										\
";

//gl_FragColor = gl_Color

/**	@ingroup	Visualization
 *	@author		Jakob Wasza
 *	@brief		Vertex shader for RImages
 *
 *	@details
 *	This vertex shader is supposed to be used with the OpenGLRImageEntity class.
 *	Its main purpose is to provide surface normals to a subsequent fragment shader.
 *	Normal computation is performed by numerical differentiation on a world-coord texture.
 *	Though the obtained normals are only of approximative nature, this vertex shader provides
 *	satisfying results while complying to real-time constraints.
 */
//texture2D(m_PrimaryPayloadTexture, gl_TexCoord[0].st);\

const char *OpenGLRImageEntity_VertexShader = "											\
	uniform sampler2D m_FlagTexture;													\
	uniform sampler2D m_WorldCoordTexture;												\
	uniform sampler2D m_PrimaryPayloadTexture;											\
	uniform sampler2D m_SecondaryPayloadTexture;										\
																						\
	varying float ValidFlag;															\
	varying vec3 Normal;																\
	varying vec3 VertexCoord;															\
	varying vec3 LightVec;																\
	varying vec4 PrimaryVertexColor;													\
	varying vec4 SecondaryVertexColor;													\
																						\
	void main()																			\
	{																					\
		gl_TexCoord[0] = gl_MultiTexCoord0;												\
		gl_TexCoord[1] = gl_MultiTexCoord1;												\
		gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;							\
																						\
		int Flag = (int)(255*texture2D(m_FlagTexture, gl_TexCoord[0].st).r);			\
		ValidFlag = Flag&0x00000001;													\
																						\
																						\
		PrimaryVertexColor = texture2D(m_PrimaryPayloadTexture, gl_TexCoord[0].st);		\
		SecondaryVertexColor = texture2D(m_SecondaryPayloadTexture, gl_TexCoord[0].st);	\
																						\
																						\
																						\
		VertexCoord = vec3(gl_ModelViewMatrix * gl_Vertex);								\
		LightVec = normalize(gl_LightSource[0].position.xyz - VertexCoord);				\
																						\
		float delta = 1e-3;																\
		vec2 CenterCoord = gl_TexCoord[0].st;											\
		vec2 x_offset = vec2(delta,0);													\
		vec2 y_offset = vec2(0,delta);													\
																						\
		vec3 xmd = vec3(texture2D(m_WorldCoordTexture, gl_TexCoord[0].st - x_offset));	\
		vec3 xpd = vec3(texture2D(m_WorldCoordTexture, gl_TexCoord[0].st + x_offset));	\
		vec3 dx = (xpd-xmd)/(2*delta);													\
		vec3 ymd = vec3(texture2D(m_WorldCoordTexture, gl_TexCoord[0].st - y_offset));	\
		vec3 ypd = vec3(texture2D(m_WorldCoordTexture, gl_TexCoord[0].st + y_offset));	\
		vec3 dy = (ypd-ymd)/(2*delta);													\
		Normal.x = dx.y*dy.z - dx.z*dy.y;												\
		Normal.y = dx.z*dy.x - dx.x*dy.z;												\
		Normal.z = dx.x*dy.y - dx.y*dy.x;												\
		Normal = normalize(gl_NormalMatrix*Normal);										\
	}																					\
";

// gl_FrontColor = gl_Color;


} // end namespace ritk

#endif // SHADERS_H___