/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/


#ifndef	__GPUMATERIALSHADER__
#define __GPUMATERIALSHADER__


		#include "gpu/gpu_shader.h"


namespace GS {
	namespace GPU {

// Static parameters influencing a material shader.
struct	MaterialShaderStaticParm
{
		bool		no_lighting;
		bool		use_alpha_test;
		bool		use_depth_bias;
		bool		use_skinning;

		bool		operator == (const MaterialShaderStaticParm &p) const
		{	return (no_lighting == p.no_lighting) && (use_alpha_test == p.use_alpha_test) && (use_depth_bias == p.use_depth_bias) && (use_skinning == p.use_skinning);	}
};

// Shader compiled for a material.
class	MaterialShader : public Render::MaterialShader
{
		Renderer	&renderer;

		String		name;

		MaterialShaderStaticParm parm;

		void		CompileForwardPointLight(Core::Shader &, bool shadow);
		void		CompileForwardSpotLight(Core::Shader &, bool shadow, bool projection_map);
		void		CompileForwardLinearLight(Core::Shader &, bool shadow);
		bool		CompileShaderSection(const char *, Core::Shader &);

public:

enum	Variant
{
		Depth,					// Shadow map program.

/*!
	@name	Deferred shading programs.
	@{
*/
		DS_GBufferMRT4,
/*!
	@}
	@name	Forward shading programs.
	@{
*/
		FS_Constant,

		FS_PointLight,
		FS_PointLightShadowMapping,

		FS_LinearLight,
		FS_LinearLightShadowMapping,

		FS_SpotLight,
		FS_SpotLightShadowMapping,
		FS_SpotLightProjection,
		FS_SpotLightProjectionShadowMapping,

		PP_NormalDepth,			// Used by the SSAO post-process.
/*!
	@}
	@name	Common programs.
	@{
*/
		PP_Velocity,
/// @}

		Last
};

		const String &GetName() const { return name; }
		const MaterialShaderStaticParm &GetStaticParm() const { return parm; }

		Array <SharedPtr <Shader> > variants;

virtual	bool		SetUserUniformValue(const char *name, const Vector4 &);
virtual	bool		SetUserUniformValue(const char *name, Render::Texture *);

		bool		SetupMaterialProgram(Variant, Core::Shader &);
		bool		Create(Render::ResourceFactory &, const Core::Shader &, const MaterialShaderStaticParm &);

		MaterialShader(Renderer &);
		~MaterialShader();
};

typedef	SharedPtr <MaterialShader> sMaterialShader;

	} // GPU
} // GS


#endif	// __GPUMATERIALSHADER__