//////////////////////////////////////////////////////////////////////
//
//                             Pixie
//
// Copyright © 1999 - 2003, Okan Arikan
//
// Contact: okan@cs.berkeley.edu
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// 
// This library 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 the GNU
// General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
//  File				:	shader.h
//  Classes				:	CShader
//							CShaderInstance
//  Description			:
//
////////////////////////////////////////////////////////////////////////
#ifndef SHADER_H
#define SHADER_H

#include "common/global.h"
#include "common/containers.h"
#include "common/os.h"
#include "xform.h"
#include "rendererc.h"
#include "fileResource.h"
#include "ri.h"
#include "variable.h"

// For forward reference
class	CShader;
class	CShaderInstance;
class	CObject;
class	CPhotonMap;
class	CAttributes;
class	CActiveLight;
class	CShaderCache;
class	CTexture;
class	CTextureInfoBase;
class	CEnvironment;
class	CCache;
class	CVolume;
class	CColorMap;
class	CVisorCache;
class	CShadingContext;
class	CPhotonHider;
class	CGatherRay;

// Meanings of the accessor field of TReference
const	unsigned int		SL_IMMEDIATE_OPERAND			=	0;
const	unsigned int		SL_PARAMETER_OPERAND			=	1;
const	unsigned int		SL_GLOBAL_OPERAND				=	2;
const	unsigned int		SL_VARYING_OPERAND				=	3;
const	unsigned int		SL_UNIFORM_OPERAND				=	4;

// This comes right after the opcode to denote the number of parameters passed to the function / opcode
typedef struct {
	unsigned	char	numArguments;			// The number of stack arguments
	unsigned	char	uniform;				// TRUE if all the arguments are uniform
	unsigned	char	numCodes;				// The number of codes after this one
	unsigned	char	plNumber;				// The parameter list number of the function
} TArguments;

// This is a variable reference
typedef struct {
	unsigned	char	numItems;				// The number of items to step for this variable (0 for constants,parameters, cardinality for variables,globals)
	unsigned	char	accessor;				// The type of the variable (SL_IMMEDIATE,SL_PARAMETER,SL_VARIABLE,SL_GLOBAL)
	unsigned	short	index;					// The index of the variable in the corresponding entry array
} TReference;

// This is the glorious TCode that holds everything
// !!!! FATAL	-	sizeof(TCode) must be 4 !!!!
typedef union {
	TArguments	arguments;
	TReference	reference;
	float		real;
	int			integer;
	const char	*string;
	void		*pointer;
} TCode;

// Shader types
const	unsigned int		SL_SURFACE						=	0;
const	unsigned int		SL_LIGHTSOURCE					=	1;
const	unsigned int		SL_DISPLACEMENT					=	2;
const	unsigned int		SL_ATMOSPHERE					=	3;
const	unsigned int		SL_IMAGER						=	4;

// Shader flags
const	unsigned int		SHADERFLAGS_NONAMBIENT			=	1;

///////////////////////////////////////////////////////////////////////
// Class				:	CShaderLookup
// Description			:	This class encapsulates a shader lookup
// Comments				:
// Date last edited		:	2/13/2003
class	CShaderLookup {
public:
							CShaderLookup();
		virtual				~CShaderLookup();
};


#define	NUMFILTERSTEPS	10

///////////////////////////////////////////////////////////////////////
// Class				:	CTextureLookup
// Description			:	This class holds information about a particular texture lookup
// Comments				:
// Date last edited		:	7/7/2001
class	CFilterLookup : public CShaderLookup	{
public:
		float				width;					// The width parameter
		RtFilterFunc		filter;					// The filter function
		float				vals[NUMFILTERSTEPS];	// The partial integrals
		float				valStep;				// The step value for the value
		float				normalizer;				// The normalizer value

		void				compute();
};

///////////////////////////////////////////////////////////////////////
// Class				:	CTextureInfoLookup
// Description			:	This class holds the base of a textureinfo lookup
// Comments				:
// Date last edited		:	02/24/2006
class	CTextureInfoLookup : public CShaderLookup	{
public:
		CTextureInfoBase	*textureInfo;
};


///////////////////////////////////////////////////////////////////////
// Class				:	CTextureLookup
// Description			:	This class holds information about a particular texture lookup
// Comments				:
// Date last edited		:	7/7/2001
class	CTextureLookup : public CShaderLookup	{
public:
		RtFilterFunc		filter;					// Lookup filter
		float				swidth,twidth;			// The filter width
		float				blur;					// Blur amount
		int					numSamples;				// The number of samples to take in the texture
		float				shadowBias;				// The shadow bias for the lookup
		int					channel;				// The start channel for the lookup
		float				fill;					// The fill in value for the lookup
		float				maxDist;				// The maximum intersection distance
		float				coneAngle;				// The coneangle
		const char			*label;					// The label of the ray
		int					lookupFloat;			// TRUE if we're only looking up a float
		CTexture			*texture;				// Points to the texture being looked up
		CEnvironment		*environment;			// Points to the environment being looked up
};

///////////////////////////////////////////////////////////////////////
// Class				:	CGlobalIllumLookup
// Description			:	This class encapsulates a global illumination lookup
// Comments				:
// Date last edited		:	2/13/2003
class	CGlobalIllumLookup : public CShaderLookup {
public:
							CGlobalIllumLookup();
							~CGlobalIllumLookup();

		int					numLookupSamples;		// The number of nearest samples to use during the map access
		float				maxDistance;			// The maximum ray intersection distance
		int					numSamples;				// The number of samples to gather for each sample
		float				maxError;				// The error knob for the sampling
		float				maxBrightness;			// The maximum brightness amount
		float				minFGRadius;			// The minimum final gather spacing
		float				maxFGRadius;			// The maximum final gather spacing
		int					irradianceIndex;		// The index of the irradiance
		int					coverageIndex;			// The index of the coverage
		int					environmentIndex;		// The index of the environment direction
		float				bias;					// The shadow bias
		int					occlusion;				// TRUE if this is an occlusion lookup
		int					gatherLocal,gatherGlobal;	// The gathering behaivor
		float				localThreshold;			// The local threshold for the radiance cache
		float				lengthA,lengthB;		// The depth to length conversion
		vector				backgroundColor;		// The color of the background for rays that don't hit anything
		CCache				*cache;					// The cache to lookup
		CPhotonMap			*map;					// The photon map to lookup
		CEnvironment		*environment;			// The environment map to use if no intersection
};

















///////////////////////////////////////////////////////////////////////
// Class				:	CGatherVariable
// Description			:	Encapsulates a variable to be saved
// Comments				:
// Date last edited		:	3/23/2003
class	CGatherVariable {
public:
	virtual	void	record(int,CGatherRay **,float **varying)	=	0;

	CGatherVariable	*next;		// The next item in the linked list
	int				shade;		// TRUE if this variable requires shading
	int				destIndex;	// The destination index
	TCode			*dest;		// The destination to save
	TCode			**destForEachLevel;	// As the name says
	TCode			**cDepth;	// The dest pointer for the current depth
};

///////////////////////////////////////////////////////////////////////
// Class				:	CShaderVectorVariable
// Description			:	Encapsulates a shader variable
// Comments				:
// Date last edited		:	3/23/2003
class	CShaderVectorVariable : public CGatherVariable {
public:

			void	record(int nr,CGatherRay **r,float **varying);

			int		entry;		// Variable index
};

///////////////////////////////////////////////////////////////////////
// Class				:	CShaderFloatVariable
// Description			:	Encapsulates a shader variable
// Comments				:
// Date last edited		:	3/23/2003
class	CShaderFloatVariable : public CGatherVariable {
public:

			void	record(int nr,CGatherRay **r,float **varying);

			int		entry;		// Variable index
};

///////////////////////////////////////////////////////////////////////
// Class				:	CRayOriginVariable
// Description			:	Ray origin variable
// Comments				:
// Date last edited		:	3/23/2003
class	CRayOriginVariable : public CGatherVariable {
public:

			void	record(int nr,CGatherRay **r,float **varying);
};

///////////////////////////////////////////////////////////////////////
// Class				:	CRayDirVariable
// Description			:	Ray direction variable
// Comments				:
// Date last edited		:	3/23/2003
class	CRayDirVariable : public CGatherVariable {
public:

			void	record(int nr,CGatherRay **r,float **varying);
};

///////////////////////////////////////////////////////////////////////
// Class				:	CRayLengthVariable
// Description			:	Ray direction variable
// Comments				:
// Date last edited		:	3/23/2003
class	CRayLengthVariable : public CGatherVariable {
public:

			void	record(int nr,CGatherRay **r,float **varying);
};


///////////////////////////////////////////////////////////////////////
// Class				:	CGatherLookup
// Description			:	Lookup parameters for the gather
// Comments				:
// Date last edited		:	3/23/2003
class	CGatherLookup : public CShaderLookup {
public:

							CGatherLookup();
							~CGatherLookup();

	void					addOutput(const char *,int);

	CGatherVariable			*outputs;				// These are the outputs that require shading
	CGatherVariable			*nonShadeOutputs;		// These are the outputs that do not require shading

	const char				*category;				// The gather category
	const char				*label;					// The ray label
	float					coneAngle;				// The distribution angle
	int						numSamples;				// The number of samples to gather
	float					bias;					// The shadow bias
	float					maxDist;				// The maximum intersection distance
	int						maxRayDepth;			// The maximum ray depth
	int						uniformDist;			// TRUE if we should sample uniformly
};


///////////////////////////////////////////////////////////////////////
// Class				:	CExplosionLookup
// Description			:	Explosion related variables
// Comments				:
// Date last edited		:	2/13/2003
class	CExplosionLookup : public CShaderLookup {
public:
		float				scatteringCoefficient;	// The scattering coefficient
		CVolume				*volume;				// The volume lookup
		CColorMap			*colormap;				// The colormap lookup
		const char			*explosionSpace;		// The space of the explosion
};

///////////////////////////////////////////////////////////////////////
// Class				:	CShader
// Description			:	This class encapsulates a shader
// Comments				:
// Date last edited		:	3/13/2001
class	CShader	: public CFileResource {
public:
	typedef struct {
		char			*name;			// Name of the parameter
		const char		*defaultValue;	// The default value of the parameter if it's a string
		EVariableType	type;			// Type of the parameter
		int				numItems;		// Number of items
		int				uniform;		// TRUE if the parameter is uniform
		CVariable		*global;		// Points to the global variable if defined
	} TShaderParameter;

public:
								CShader(const char *);
								~CShader();

		void					nullify();						// Make sure the shader is never executed again

		int						type;							// Type of the shader

		TShaderParameter		*parameters;					// Array of parameters

		TCode					*memory;						// The memory base allocated for this shader
		TCode					*codeArea;						// The code array
		TCode					*parametersArea;				// The parameter values
		TCode					*constantsArea;					// The constant values
		int						totalParameterSize;				// Total memory needed by the parameters
		TCode					**parameterEntries;				// The parameter entries
		int						*parameterDisplacements;		// The parameter displacements
		TCode					**constantEntries;				// The constant entries

		int						*varyingSizes;
		int						totalVaryingSize;

		int						*uniformSizes;
		int						totalUniformSize;

		char					**strings;						// Strings used by the shader

		int						numParameters;					// Number of parameters
		int						numGlobals;						// Number of global parameters
		int						numStrings;						// Number of strings
		int						numVariables;					// Number of variables
		int						numUniforms;
		int						numPLs;							// Number of parameter lists

		int						codeEntryPoint;					// Index into code array where the actual code starts
		int						initEntryPoint;					// Index into code array where the init code starts

		int						usedParameters;

		CShaderCache			*cache;
		int						dirty;							// TRUE if the shader has been cached in the last frame

		friend	CShader			*parseShader(const char *,const char *);
};


///////////////////////////////////////////////////////////////////////
// Class				:	CShaderInstance
// Description			:	This class encapsulates an instance of a shader
// Comments				:
// Date last edited		:	3/10/2001
class	CShaderInstance {
public:
								CShaderInstance(CAttributes *,CXform *);
		virtual					~CShaderInstance();

		void					attach()	{	refCount++;	}
		void					detach()	{	refCount--; if (refCount == 0) delete this; }
		void					check()		{	if (refCount == 0)	delete this;			}

		virtual	void			illuminate(CShadingContext *)							=	0;
		virtual	void			setParameters(int,char **,void **)						=	0;
		virtual int				getParameter(const char *,void *,CVariable**,int*)		=	0;
		virtual	void			execute(CShadingContext *)								=	0;
		virtual	unsigned int	requiredParameters()									=	0;
		virtual	void			registerDefaults(CAttributes *,CActiveLight *light = 0)	=	0;
		virtual	const char		*getName()												=	0;
		
		void					createCategories();

		int						refCount;						// The refcount to manage the clones
		CXform					*xform;
		int						*categories;					// Categories for light shaders
		unsigned int			flags;
};

///////////////////////////////////////////////////////////////////////
// Class				:	CShaderInstance
// Description			:	This class encapsulates an instance of a shader
// Comments				:
// Date last edited		:	3/10/2001
class	CProgrammableShaderInstance : public CShaderInstance {
public:
								CProgrammableShaderInstance(CShader *,CAttributes *,CXform *);
		virtual					~CProgrammableShaderInstance();

		void					illuminate(CShadingContext *);
		void					setParameters(int,char **,void **);
		int						getParameter(const char *,void *,CVariable**,int*);	// Get the value of a parameter
		void					execute(CShadingContext *);							// Execute the shader
		unsigned int			requiredParameters();
		void					registerDefaults(CAttributes *,CActiveLight *light);
		const char				*getName();

		CShader					*parent;						// The parent shader
		TCode					*parametersArea;
		TCode					**parameterEntries;
		int						numStrings;						// The number of strings allocated for this instance
		char					**strings;						// The strings allocated for this shader
		CShaderLookup			**parameterLists;				// The parameter lists
		int						dirty;							// TRUE if the shader is dirty
private:
		int						setParameter(char *,void *);
};

#endif
