2
0
Panagiotis Christopoulos Charitos 14 жил өмнө
parent
commit
d6d7137928

+ 14 - 0
shaders/MaterialFragmentVariables.glsl

@@ -0,0 +1,14 @@
+/// @name Varyings
+/// @{
+in vec3 vNormal;
+in vec3 vTangent;
+in float vTangentW;
+in vec2 vTexCoords;
+in vec3 vVertPosViewSpace;
+/// @}
+
+if !defined(DEPTH_PASS)
+layout(location = 0) out vec3 fMsNormalFai;
+layout(location = 1) out vec3 fMsDiffuseFai;
+layout(location = 2) out vec4 fMsSpecularFai;
+#endif

+ 50 - 0
shaders/MaterialVert.glsl

@@ -0,0 +1,50 @@
+/// @file
+/// Generic vertex shader for material passes (both color and depth)
+
+/// @name Attributes
+/// @{
+in vec3 position;
+in vec3 normal;
+in vec2 texCoords;
+in vec4 tangent;
+/// @}
+
+/// @name Uniforms
+/// @{
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 projectionMat;
+uniform mat4 modelViewMat;
+uniform mat3 normalMat;
+uniform mat4 modelViewProjectionMat;
+/// @}
+
+/// @name Varyings
+/// @{
+out vec3 vNormal;
+out vec2 vTexCoords;
+out vec3 vTangent;
+out float vTangentW;
+out vec3 vVertPosViewSpace; ///< For env mapping. AKA view vector
+/// @}
+
+
+
+//==============================================================================
+// main                                                                        =
+//==============================================================================
+void main()
+{
+	// calculate the vert pos, normal and tangent
+	vNormal = normalMat * normal;
+
+	gl_Position = modelViewProjectionMat * vec4(position, 1.0);
+
+	// calculate the rest
+	vTexCoords = texCoords;
+
+	vTangent = normalMat * vec3(tangent);
+	vTangentW = tangent.w;
+
+	vVertPosViewSpace = vec3(modelViewMat * vec4(position, 1.0));
+}

+ 2 - 2
src/GfxApi/GlStateMachine.h

@@ -26,6 +26,8 @@ class GlStateMachine
 		void useShaderProg(GLuint id);
 
 		void setViewport(uint x, uint y, uint w, uint h);
+
+		static GLuint getCurrentProgramGlId();
 		/// @}
 
 	private:
@@ -41,8 +43,6 @@ class GlStateMachine
 		GLsizei viewportW;
 		GLsizei viewportH;
 		/// @}
-
-		static GLuint getCurrentProgramGlId();
 };
 
 

+ 71 - 40
src/Resources/BuildinMaterialVariable.cpp

@@ -1,38 +1,63 @@
 #include "BuildinMaterialVariable.h"
 #include "Util/Exception.h"
+#include "Util/Assert.h"
 #include <cstring>
 #include <boost/lexical_cast.hpp>
+#include <boost/assign/list_of.hpp>
 
 
 //==============================================================================
 // Statics                                                                     =
 //==============================================================================
 
-boost::array<BuildinMaterialVariable::BuildinVarInfo,
-	BuildinMaterialVariable::BV_NUM> BuildinMaterialVariable::infos =
-{{
-	{"position", GL_FLOAT_VEC3},
-	{"tangent", GL_FLOAT_VEC4},
-	{"normal", GL_FLOAT_VEC3},
-	{"texCoords", GL_FLOAT_VEC2},
-	{"modelMat", GL_FLOAT_MAT4},
-	{"viewMat", GL_FLOAT_MAT4},
-	{"projectionMat", GL_FLOAT_MAT4},
-	{"modelViewMat", GL_FLOAT_MAT4},
-	{"viewProjectionMat", GL_FLOAT_MAT4},
-	{"normalMat", GL_FLOAT_MAT3},
-	{"modelViewProjectionMat", GL_FLOAT_MAT4},
-	{"msNormalFai", GL_SAMPLER_2D},
-	{"msDiffuseFai", GL_SAMPLER_2D},
-	{"msSpecularFai", GL_SAMPLER_2D},
-	{"msDepthFai", GL_SAMPLER_2D},
-	{"isFai", GL_SAMPLER_2D},
-	{"ppsPrePassFai", GL_SAMPLER_2D},
-	{"ppsPostPassFai", GL_SAMPLER_2D},
-	{"rendererSize", GL_FLOAT_VEC2},
-	{"sceneAmbientColor", GL_FLOAT_VEC3},
-	{"blurring", GL_FLOAT},
-}};
+ConstCharPtrHashMap<BuildinMaterialVariable::BuildinVariable>::Type
+	BuildinMaterialVariable::buildinNameToEnum = boost::assign::map_list_of
+	("position", BV_POSITION)
+	("tangent", BV_TANGENT)
+	("normal", BV_NORMAL)
+	("texCoords", BV_TEX_COORDS)
+	("modelMat", BV_MODEL_MAT)
+	("viewMat", BV_VIEW_MAT)
+	("projectionMat", BV_PROJECTION_MAT)
+	("modelViewMat", BV_MODELVIEW_MAT)
+	("viewProjectionMat", BV_VIEWPROJECTION_MAT)
+	("normalMat", BV_NORMAL_MAT)
+	("modelViewProjectionMat", BV_MODELVIEWPROJECTION_MAT)
+	("msNormalFai", BV_MS_NORMAL_FAI)
+	("msDiffuseFai", BV_MS_DIFFUSE_FAI)
+	("msSpecularFai", BV_MS_SPECULAR_FAI)
+	("msDepthFai", BV_MS_DEPTH_FAI)
+	("isFai", BV_IS_FAI)
+	("ppsPrePassFai", BV_PPS_PRE_PASS_FAI)
+	("ppsPostPassFai", BV_PPS_POST_PASS_FAI)
+	("rendererSize", BV_RENDERER_SIZE)
+	("sceneAmbientColor", BV_SCENE_AMBIENT_COLOR)
+	("blurring", BV_BLURRING);
+
+
+boost::unordered_map<BuildinMaterialVariable::BuildinVariable, GLenum>
+	BuildinMaterialVariable::buildinToGlType = boost::assign::map_list_of
+	(BV_POSITION, GL_FLOAT_VEC3)
+	(BV_TANGENT, GL_FLOAT_VEC4)
+	(BV_NORMAL, GL_FLOAT_VEC3)
+	(BV_TEX_COORDS, GL_FLOAT_VEC2)
+	(BV_MODEL_MAT, GL_FLOAT_MAT4)
+	(BV_VIEW_MAT, GL_FLOAT_MAT4)
+	(BV_PROJECTION_MAT, GL_FLOAT_MAT4)
+	(BV_PROJECTION_MAT, GL_FLOAT_MAT4)
+	(BV_VIEWPROJECTION_MAT, GL_FLOAT_MAT4)
+	(BV_NORMAL_MAT, GL_FLOAT_MAT3)
+	(BV_MODELVIEWPROJECTION_MAT, GL_FLOAT_MAT4)
+	(BV_MS_NORMAL_FAI, GL_SAMPLER_2D)
+	(BV_MS_DIFFUSE_FAI, GL_SAMPLER_2D)
+	(BV_MS_SPECULAR_FAI, GL_SAMPLER_2D)
+	(BV_MS_DEPTH_FAI, GL_SAMPLER_2D)
+	(BV_IS_FAI, GL_SAMPLER_2D)
+	(BV_PPS_PRE_PASS_FAI, GL_SAMPLER_2D)
+	(BV_PPS_POST_PASS_FAI, GL_SAMPLER_2D)
+	(BV_RENDERER_SIZE, GL_FLOAT_VEC2)
+	(BV_SCENE_AMBIENT_COLOR, GL_FLOAT_VEC3)
+	(BV_BLURRING, GL_FLOAT);
 
 
 //==============================================================================
@@ -66,22 +91,28 @@ BuildinMaterialVariable::BuildinMaterialVariable(
 bool BuildinMaterialVariable::isBuildin(const char* name,
 	BuildinVariable* var, GLenum* dataType)
 {
-	for(uint i = 0; i < BV_NUM; i++)
+	ConstCharPtrHashMap<BuildinVariable>::Type::const_iterator it =
+		buildinNameToEnum.find(name);
+
+	if(it == buildinNameToEnum.end())
+	{
+		return false;
+	}
+
+	if(var)
 	{
-		if(!strcmp(infos[i].name, name))
-		{
-			if(var)
-			{
-				*var = static_cast<BuildinVariable>(i);
-			}
-
-			if(dataType)
-			{
-				*dataType = infos[i].dataType;
-			}
-			return true;
-		}
+		*var = it->second;
+	}
+
+	if(dataType)
+	{
+		boost::unordered_map<BuildinVariable, GLenum>::const_iterator it2 =
+			buildinToGlType.find(it->second);
+
+		ASSERT(it2 != buildinToGlType.end());
+
+		*dataType = it2->second;
 	}
 
-	return false;
+	return true;
 }

+ 7 - 8
src/Resources/BuildinMaterialVariable.h

@@ -2,6 +2,7 @@
 #define BUILDIN_MATERIAL_VARIABLE_H
 
 #include "MaterialVariable.h"
+#include "Util/ConstCharPtrHashMap.h"
 #include <boost/array.hpp>
 
 
@@ -43,13 +44,6 @@ class BuildinMaterialVariable: public MaterialVariable
 			BV_NUM ///< The number of all variables
 		};
 
-		/// Information for the build-in shader program variables
-		struct BuildinVarInfo
-		{
-			const char* name; ///< Variable name
-			GLenum dataType; ///< aka GL data type
-		};
-
 		BuildinMaterialVariable(const SProgVar* cpSProgVar,
 			const SProgVar* dpSProgVar, const char* name);
 
@@ -59,7 +53,12 @@ class BuildinMaterialVariable: public MaterialVariable
 			GLenum* dataType = NULL);
 
 	private:
-		static boost::array<BuildinVarInfo, BV_NUM> infos;
+		/// Given a name of a variable find its BuildinVariable enum
+		static ConstCharPtrHashMap<BuildinVariable>::Type buildinNameToEnum;
+
+		/// Given a BuildinVariable enum it gives the GL type
+		static boost::unordered_map<BuildinVariable, GLenum> buildinToGlType;
+
 		BuildinVariable var;
 };
 

+ 77 - 453
src/Resources/Material2.cpp

@@ -1,46 +1,38 @@
 #include "Material2.h"
 #include "MaterialVariable.h"
-#include "Util/Scanner/Scanner.h"
-#include "Misc/Parser.h"
 #include "Misc/PropertyTree.h"
-#include <sstream>
+#include "MaterialShaderProgramCreator.h"
+#include "Core/App.h"
+#include "Core/Globals.h"
 #include <boost/foreach.hpp>
 #include <boost/property_tree/ptree.hpp>
 #include <boost/property_tree/xml_parser.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/functional/hash.hpp>
 
 
 //==============================================================================
 // Statics                                                                     =
 //==============================================================================
 
-Material2::BlendParam Material2::blendingParams[] =
-{
-	{GL_ZERO, "GL_ZERO"},
-	{GL_ONE, "GL_ONE"},
-	{GL_DST_COLOR, "GL_DST_COLOR"},
-	{GL_ONE_MINUS_DST_COLOR, "GL_ONE_MINUS_DST_COLOR"},
-	{GL_SRC_ALPHA, "GL_SRC_ALPHA"},
-	{GL_ONE_MINUS_SRC_ALPHA, "GL_ONE_MINUS_SRC_ALPHA"},
-	{GL_DST_ALPHA, "GL_DST_ALPHA"},
-	{GL_ONE_MINUS_DST_ALPHA, "GL_ONE_MINUS_DST_ALPHA"},
-	{GL_SRC_ALPHA_SATURATE, "GL_SRC_ALPHA_SATURATE"},
-	{GL_SRC_COLOR, "GL_SRC_COLOR"},
-	{GL_ONE_MINUS_SRC_COLOR, "GL_ONE_MINUS_SRC_COLOR"},
-	{0, NULL}
-};
-
-
-Material2::GlDataToText Material2::glDataToText[] =
-{
-	{GL_FLOAT, "float"},
-	{GL_FLOAT_VEC2, "vec2"},
-	{GL_FLOAT_VEC3, "vec3"},
-	{GL_FLOAT_VEC4, "vec4"},
-	{GL_SAMPLER_2D, "sampler2D"},
-	{GL_FLOAT_MAT3, "mat3"},
-	{GL_FLOAT_MAT4, "mat4"},
-	{0, NULL},
-};
+// Dont make idiotic mistakes
+#define TXT_AND_ENUM(x) \
+	(#x, x)
+
+
+ConstCharPtrHashMap<GLenum>::Type Material2::txtToBlengGlEnum =
+	boost::assign::map_list_of
+	TXT_AND_ENUM(GL_ZERO)
+	TXT_AND_ENUM(GL_ONE)
+	TXT_AND_ENUM(GL_DST_COLOR)
+	TXT_AND_ENUM(GL_ONE_MINUS_DST_COLOR)
+	TXT_AND_ENUM(GL_SRC_ALPHA)
+	TXT_AND_ENUM(GL_ONE_MINUS_SRC_ALPHA)
+	TXT_AND_ENUM(GL_DST_ALPHA)
+	TXT_AND_ENUM(GL_ONE_MINUS_DST_ALPHA)
+	TXT_AND_ENUM(GL_SRC_ALPHA_SATURATE)
+	TXT_AND_ENUM(GL_SRC_COLOR)
+	TXT_AND_ENUM(GL_ONE_MINUS_SRC_COLOR);
 
 
 //==============================================================================
@@ -64,289 +56,6 @@ Material2::~Material2()
 {}
 
 
-//==============================================================================
-// parseShaderFileForFunctionDefinitions                                       =
-//==============================================================================
-void Material2::parseShaderFileForFunctionDefinitions(const char* filename,
-	boost::ptr_vector<FuncDefinition>& out)
-{
-	Scanner::Scanner scanner(filename, false);
-	const Scanner::Token* token = &scanner.getCrntToken();
-
-	// Forever
-	while(true)
-	{
-		getNextTokenAndSkipNewline(scanner);
-		FuncDefinition* funcDef = NULL;
-
-		// EOF
-		if(token->getCode() == Scanner::TC_EOF)
-		{
-			break;
-		}
-		// #
-		else if(token->getCode() == Scanner::TC_SHARP)
-		{
-			parseUntilNewline(scanner);
-			continue;
-		}
-		// Type
-		else if(token->getCode() == Scanner::TC_IDENTIFIER)
-		{
-			funcDef = new FuncDefinition;
-			out.push_back(funcDef);
-
-			if(!strcmp(token->getValue().getString(), "float"))
-			{
-				funcDef->returnArg = AT_FLOAT;
-			}
-			else if(!strcmp(token->getValue().getString(), "vec2"))
-			{
-				funcDef->returnArg = AT_VEC2;
-			}
-			else if(!strcmp(token->getValue().getString(), "vec3"))
-			{
-				funcDef->returnArg = AT_VEC3;
-			}
-			else if(!strcmp(token->getValue().getString(), "vec4"))
-			{
-				funcDef->returnArg = AT_VEC4;
-			}
-			else if(!strcmp(token->getValue().getString(), "void"))
-			{
-				funcDef->returnArg = AT_VOID;
-			}
-			else
-			{
-				throw PARSER_EXCEPTION_EXPECTED("float or vec2 or vec3"
-					" or vec4 or void");
-			}
-		}
-		else
-		{
-			throw PARSER_EXCEPTION_EXPECTED("identifier");
-		}
-
-		// Function name
-		getNextTokenAndSkipNewline(scanner);
-		if(token->getCode() != Scanner::TC_IDENTIFIER)
-		{
-			throw PARSER_EXCEPTION_EXPECTED("identifier");
-		}
-
-		funcDef->name = token->getValue().getString();
-
-		// (
-		getNextTokenAndSkipNewline(scanner);
-		if(token->getCode() != Scanner::TC_LPAREN)
-		{
-			throw PARSER_EXCEPTION_EXPECTED("(");
-		}
-
-		// Arguments
-		while(true)
-		{
-			ArgDefinition* argDef = new ArgDefinition;
-			funcDef->argDefinitions.push_back(argDef);
-
-			// Call type
-			getNextTokenAndSkipNewline(scanner);
-			if(token->getCode() != Scanner::TC_IDENTIFIER)
-			{
-				throw PARSER_EXCEPTION_EXPECTED("identifier");
-			}
-
-			if(!strcmp(token->getValue().getString(), "in"))
-			{
-				argDef->callType = ACT_IN;
-			}
-			else if(!strcmp(token->getValue().getString(), "out"))
-			{
-				argDef->callType = ACT_OUT;
-			}
-			else if(!strcmp(token->getValue().getString(), "inout"))
-			{
-				argDef->callType = ACT_INOUT;
-			}
-			else
-			{
-				throw PARSER_EXCEPTION_EXPECTED("in or out or inout");
-			}
-
-			// Type
-			getNextTokenAndSkipNewline(scanner);
-			if(token->getCode() != Scanner::TC_IDENTIFIER)
-			{
-				throw PARSER_EXCEPTION_EXPECTED("identifier");
-			}
-
-			if(!strcmp(token->getValue().getString(), "float"))
-			{
-				argDef->dataType = AT_FLOAT;
-			}
-			else if(!strcmp(token->getValue().getString(), "vec2"))
-			{
-				argDef->dataType = AT_VEC2;
-			}
-			else if(!strcmp(token->getValue().getString(), "vec3"))
-			{
-				argDef->dataType = AT_VEC3;
-			}
-			else if(!strcmp(token->getValue().getString(), "vec4"))
-			{
-				argDef->dataType = AT_VEC4;
-			}
-			else if(!strcmp(token->getValue().getString(), "sampler2D"))
-			{
-				argDef->dataType = AT_TEXTURE;
-			}
-			else
-			{
-				throw PARSER_EXCEPTION_EXPECTED("float or vec2 or vec3 or"
-					" vec4 or sampler2D");
-			}
-
-			// Name
-			getNextTokenAndSkipNewline(scanner);
-			if(token->getCode() != Scanner::TC_IDENTIFIER)
-			{
-				throw PARSER_EXCEPTION_EXPECTED("identifier");
-			}
-
-			argDef->name = token->getValue().getString();
-
-			// ,
-			getNextTokenAndSkipNewline(scanner);
-			if(token->getCode() == Scanner::TC_COMMA)
-			{
-				continue;
-			}
-			// )
-			else if(token->getCode() == Scanner::TC_RPAREN)
-			{
-				break;
-			}
-			else
-			{
-				throw PARSER_EXCEPTION_UNEXPECTED();
-			}
-		} // End arguments
-
-
-		// {
-		getNextTokenAndSkipNewline(scanner);
-		if(token->getCode() != Scanner::TC_LBRACKET)
-		{
-			throw PARSER_EXCEPTION_EXPECTED("{");
-		}
-
-		// Skip until closing bracket
-		int bracketsNum = 0;
-		while(true)
-		{
-			getNextTokenAndSkipNewline(scanner);
-
-			if(token->getCode() == Scanner::TC_RBRACKET)
-			{
-				if(bracketsNum == 0)
-				{
-					break;
-				}
-				--bracketsNum;
-			}
-			else if(token->getCode() == Scanner::TC_LBRACKET)
-			{
-				++bracketsNum;
-			}
-			else if(token->getCode() == Scanner::TC_EOF)
-			{
-				throw PARSER_EXCEPTION_UNEXPECTED();
-			}
-			else
-			{
-				continue;
-			}
-		} // End until closing bracket
-
-		/*std::stringstream ss;
-		ss << "Func def: " << funcDef->returnArg << " " << funcDef->name << " ";
-		BOOST_FOREACH(const ArgDefinition& adef, funcDef->argDefinitions)
-		{
-			ss << adef.callType << " " << adef.dataType << " " <<
-				adef.name << ", ";
-		}
-		std::cout << ss.str() << std::endl;*/
-	} // End for all functions
-}
-
-
-//==============================================================================
-// parseUntilNewline                                                           =
-//==============================================================================
-void Material2::parseUntilNewline(Scanner::Scanner& scanner)
-{
-	const Scanner::Token* token = &scanner.getCrntToken();
-	Scanner::TokenCode prevTc;
-
-	while(true)
-	{
-		prevTc = token->getCode();
-		scanner.getNextToken();
-
-		if(token->getCode() == Scanner::TC_EOF)
-		{
-			break;
-		}
-		else if(token->getCode() == Scanner::TC_NEWLINE &&
-			prevTc != Scanner::TC_BACK_SLASH)
-		{
-			break;
-		}
-	}
-}
-
-
-//==============================================================================
-// getNextTokenAndSkipNewline                                                  =
-//==============================================================================
-void Material2::getNextTokenAndSkipNewline(Scanner::Scanner& scanner)
-{
-	const Scanner::Token* token;
-
-	while(true)
-	{
-		token = &scanner.getNextToken();
-		if(token->getCode() != Scanner::TC_NEWLINE)
-		{
-			break;
-		}
-	}
-}
-
-
-//==============================================================================
-// getGlBlendEnumFromText                                                      =
-//==============================================================================
-int Material2::getGlBlendEnumFromText(const char* str)
-{
-	BlendParam* ptr = &blendingParams[0];
-	while(true)
-	{
-		if(ptr->str == NULL)
-		{
-			throw EXCEPTION("Incorrect blending factor: " + str);
-		}
-
-		if(!strcmp(ptr->str, str))
-		{
-			return ptr->glEnum;
-		}
-
-		++ptr;
-	}
-}
-
-
 //==============================================================================
 // parseMaterialTag                                                            =
 //==============================================================================
@@ -382,12 +91,36 @@ void Material2::parseMaterialTag(const boost::property_tree::ptree& pt)
 	if(blendFuncsTree)
 	{
 		// sFactor
-		blendingSfactor = getGlBlendEnumFromText(
-			blendFuncsTree.get().get<std::string>("sFactor").c_str());
+		{
+			const std::string& tmp =
+				blendFuncsTree.get().get<std::string>("sFactor");
+
+			ConstCharPtrHashMap<GLenum>::Type::const_iterator it =
+				txtToBlengGlEnum.find(tmp.c_str());
+
+			if(it == txtToBlengGlEnum.end())
+			{
+				throw EXCEPTION("Incorrect blend enum: " + tmp);
+			}
+
+			blendingSfactor = it->second;
+		}
 
 		// dFactor
-		blendingDfactor = getGlBlendEnumFromText(
-			blendFuncsTree.get().get<std::string>("dFactor").c_str());
+		{
+			const std::string& tmp =
+				blendFuncsTree.get().get<std::string>("dFactor");
+
+			ConstCharPtrHashMap<GLenum>::Type::const_iterator it =
+				txtToBlengGlEnum.find(tmp.c_str());
+
+			if(it == txtToBlengGlEnum.end())
+			{
+				throw EXCEPTION("Incorrect blend enum: " + tmp);
+			}
+
+			blendingDfactor = it->second;
+		}
 	}
 
 	//
@@ -413,124 +146,48 @@ void Material2::parseMaterialTag(const boost::property_tree::ptree& pt)
 	//
 	// shaderProgram
 	//
-	parseShaderProgramTag(pt.get_child("shaderProgram"));
-}
-
-
-//==============================================================================
-// parseShaderProgramTag                                                       =
-//==============================================================================
-void Material2::parseShaderProgramTag(const boost::property_tree::ptree& pt)
-{
-	using namespace boost::property_tree;
-
-	Vec<std::string> srcLines;
-
-	//
-	// <includes></includes>
-	//
-	boost::ptr_vector<FuncDefinition> funcDefs;
-	Vec<std::string> includeLines;
-
-	const ptree& includesPt = pt.get_child("includes");
-	BOOST_FOREACH(const ptree::value_type& v, includesPt)
-	{
-		if(v.first != "include")
-		{
-			throw EXCEPTION("Expected include and not: " + v.first);
-		}
-
-		const std::string& fname = v.second.data();
-		//parseShaderFileForFunctionDefinitions(fname.c_str(), funcDefs);
-
-		includeLines.push_back("#pragma anki include \"" + fname + "\"");
-	}
-
-	std::sort(includeLines.begin(), includeLines.end(), compareStrings);
-	srcLines.insert(srcLines.end(), includeLines.begin(), includeLines.end());
-
-	//
-	// <ins></ins>
-	//
-	Vec<std::string> uniformsLines; // Store the source of the uniform vars
-
-	boost::optional<const ptree&> insPt = pt.get_child_optional("ins");
-	if(insPt)
-	{
-		BOOST_FOREACH(const ptree::value_type& v, insPt.get())
-		{
-			if(v.first != "in")
-			{
-				throw EXCEPTION("Expected in and not: " + v.first);
-			}
+	MaterialShaderProgramCreator mspc(pt.get_child("shaderProgram"));
 
-			const ptree& inPt = v.second;
-			parseInTag(inPt, uniformsLines);
-		} // end for all ins
+	const std::string& cpSrc = mspc.getShaderProgramSource();
+	std::string dpSrc = "#define DEPTH_PASS\n" + cpSrc;
 
-		std::sort(uniformsLines.begin(), uniformsLines.end(), compareStrings);
-		srcLines.insert(srcLines.end(), uniformsLines.begin(),
-			uniformsLines.end());
-	}
-
-	//
-	//
-	//
-	std::string src;
-	BOOST_FOREACH(const std::string& line, srcLines)
-	{
-		src += line + "\n";
-	}
-
-	std::cout << src << std::endl;
+	createShaderProgSourceToCache(cpSrc);
+	createShaderProgSourceToCache(dpSrc);
 }
 
 
 //==============================================================================
-// parseInTag                                                                  =
+// createShaderProgSourceToCache                                               =
 //==============================================================================
-void Material2::parseInTag(const boost::property_tree::ptree& pt,
-	Vec<std::string>& sourceLines)
+std::string Material2::createShaderProgSourceToCache(const std::string& source)
 {
-	const std::string& name = pt.get<std::string>("name");
+	// Create the hash
+	boost::hash<std::string> stringHash;
+	std::size_t h = stringHash(source);
+	std::string prefix = boost::lexical_cast<std::string>(h);
 
-	std::string line = "uniform ";
+	// Create path XXX
+	/*boost::filesystem::path newfPathName =
+		AppSingleton::getInstance().getCachePath() / (prefix + ".glsl");*/
+	boost::filesystem::path newfPathName =
+		boost::filesystem::path("/users/panoscc/.anki/cache") / (prefix + ".glsl");
 
-	if(pt.get_child_optional("float"))
-	{
-		line += "float";
-	}
-	else if(pt.get_child_optional("vec2"))
-	{
-		line += "vec2";
-	}
-	else if(pt.get_child_optional("vec3"))
-	{
-		line += "vec3";
-	}
-	else if(pt.get_child_optional("vec4"))
-	{
-		line += "vec4";
-	}
-	else if(pt.get_child_optional("sampler2D"))
-	{
-		line += "sampler2D";
-	}
-	else
-	{
-		BuildinMaterialVariable::BuildinVariable tmp;
-		GLenum dataType;
 
-		if(!BuildinMaterialVariable::isBuildin(name.c_str(), &tmp, &dataType))
+	// If file not exists write it
+	if(!boost::filesystem::exists(newfPathName))
+	{
+		// If not create it
+		std::ofstream f(newfPathName.string().c_str());
+		if(!f.is_open())
 		{
-			throw EXCEPTION("The variable is not build in: " + name);
+			throw EXCEPTION("Cannot open file for writing: " +
+				newfPathName.string());
 		}
 
-		line += getTextFromGlType(dataType);
+		f.write(source.c_str(), source.length());
 	}
 
-	line += " " + name + ";";
-	sourceLines.push_back(line);
+	return newfPathName.string();
 }
 
 
@@ -552,36 +209,3 @@ void Material2::load(const char* filename)
 	}
 }
 
-
-//==============================================================================
-// compareStrings                                                              =
-//==============================================================================
-bool Material2::compareStrings(const std::string& a, const std::string& b)
-{
-	return a < b;
-}
-
-
-//==============================================================================
-// getTextFromGlType                                                           =
-//==============================================================================
-const char* Material2::getTextFromGlType(GLenum dataType)
-{
-	GlDataToText* ptr = &glDataToText[0];
-
-	while(true)
-	{
-		if(ptr->txt == NULL)
-		{
-			throw EXCEPTION("Incorrect GL data type");
-		}
-
-		if(ptr->dataType == dataType)
-		{
-			return ptr->txt;
-		}
-
-		++ptr;
-	}
-}
-

+ 22 - 124
src/Resources/Material2.h

@@ -2,7 +2,7 @@
 #define MATERIAL_2_H
 
 #include "Util/Accessors.h"
-#include "Util/CharPtrHashMap.h"
+#include "Util/ConstCharPtrHashMap.h"
 #include "UserMaterialVariable.h"
 #include "BuildinMaterialVariable.h"
 #include "RsrcPtr.h"
@@ -37,6 +37,18 @@ struct MaterialProperties
 };
 
 
+/// Material resource
+///
+/// Every material keeps info of how to render a RenedrableNode. Using a node
+/// based logic it creates a couple of shader programs dynamically. One for
+/// color passes and one for depth. It also keeps two sets of material
+/// variables. The first is the build in and the second the user defined.
+/// During the renderer's shader setup the buildins will be set automatically,
+/// for the user variables the user needs to have its value in the material
+/// file. Some material variables may be present in both shader programs and
+/// some in only one of them
+///
+/// Material XML file format:
 /// @code
 /// <material>
 /// 	<castsShadow>true | false</castsShadow>
@@ -59,7 +71,7 @@ struct MaterialProperties
 /// 		</includes>
 ///
 /// 		<ins>
-/// 			<in>
+/// 			<in> *
 /// 				<name>xx</name>
 /// 				<value>
 /// 					<float>0.0</float> |
@@ -75,16 +87,17 @@ struct MaterialProperties
 /// 			<operation>
 /// 				<id>x</id>
 /// 				<function>functionName</function>
-/// 				<parameters>
-/// 					<parameter>xx</parameter>
-/// 					<parameter>yy</parameter>
-/// 				</parameters>
+/// 				<arguments>
+/// 					<argument>xx</argument>
+/// 					<argument>yy</argument>
+/// 				</arguments>
 /// 			</operation>
 /// 		</operations>
 ///
 /// 	</shaderProgram>
 /// </material>
 /// @endcode
+/// *: For "in" if the value is not set then the in variable will be build in
 class Material2: private MaterialProperties
 {
 	public:
@@ -112,14 +125,6 @@ class Material2: private MaterialProperties
 
 		const ShaderProg& getDepthPassShaderProgram() const
 			{return *dpShaderProg;}
-
-		/*/// Return NULL if the variable is not present in the shader program
-		const SProgAttribVar* getStandardAttributeVariable(
-			StandardAtributeVariables id) const;
-
-		/// Return NULL if the variable is not present in the shader program
-		const SProgUniVar* getStandardUniformVariable(
-			StandardUniformVariables id) const;*/
 		/// @}
 
 		/// Return false if blendingSfactor is equal to GL_ONE and
@@ -130,67 +135,6 @@ class Material2: private MaterialProperties
 		void load(const char* filename);
 
 	public: /// XXX
-		//======================================================================
-		// Nested                                                              =
-		//======================================================================
-
-		/// Function argument data type
-		enum ArgDataType
-		{
-			AT_TEXTURE,
-			AT_FLOAT,
-			AT_VEC2,
-			AT_VEC3,
-			AT_VEC4,
-			AT_VOID
-		};
-
-		/// Function argument data call type
-		enum ArgCallType
-		{
-			ACT_IN,
-			ACT_OUT,
-			ACT_INOUT
-		};
-
-		/// Function argument definition
-		struct ArgDefinition
-		{
-			std::string name;
-			ArgDataType dataType;
-			ArgCallType callType;
-		};
-
-		/// Function definition. It contains information about a function (eg
-		/// return type and the arguments)
-		struct FuncDefinition
-		{
-			std::string name; ///< Function name
-			boost::ptr_vector<ArgDefinition> argDefinitions;
-			ArgDataType returnArg;
-		};
-
-		/// Information for the build-in shader program variables
-		struct BuildinVar
-		{
-			const char* varName;
-			GLenum dataType; ///< aka GL data type
-		};
-
-		/// Simple pair structure
-		struct BlendParam
-		{
-			int glEnum;
-			const char* str;
-		};
-
-		/// Simple pair structure
-		struct GlDataToText
-		{
-			GLenum dataType;
-			const char* txt;
-		};
-
 		//======================================================================
 		// Members                                                             =
 		//======================================================================
@@ -210,50 +154,18 @@ class Material2: private MaterialProperties
 		/// Shader program for depth passes
 		RsrcPtr<ShaderProg> dpShaderProg;
 
-		/// Used to go from text to actual GL enum
-		static BlendParam blendingParams[];
-
-		/// XXX
-		static GlDataToText glDataToText[];
+		/// From "GL_ZERO" return GL_ZERO
+		static ConstCharPtrHashMap<GLenum>::Type txtToBlengGlEnum;
 
 		//======================================================================
 		// Methods                                                             =
 		//======================================================================
 
-		/// XXX Appends
-		static void parseShaderFileForFunctionDefinitions(const char* filename,
-			boost::ptr_vector<FuncDefinition>& out);
-
-		/// XXX
-		/// Used by parseShaderFileForFunctionDefinitions. Takes into account
-		/// the backslashes
-		static void parseUntilNewline(Scanner::Scanner& scanner);
-
-		/// It being used by parseShaderFileForFunctionDefinitions and it
-		/// skips until newline after a '#' found. It takes into account the
-		/// back slashes that the preprocessos may have
-		static void getNextTokenAndSkipNewline(Scanner::Scanner& scanner);
-
-		/// Searches the blendingParams array for text. It throw exception if
-		/// not found
-		static int getGlBlendEnumFromText(const char* str);
-
 		/// Parse what is within the @code <material></material> @endcode
 		void parseMaterialTag(const boost::property_tree::ptree& pt);
 
-		/// Parse what is within the
-		/// @code <shaderProgram></shaderProgram> @endcode
-		void parseShaderProgramTag(const boost::property_tree::ptree& pt);
-
-		/// Parse what is within the @code <in></in> @endcode
-		void parseInTag(const boost::property_tree::ptree& pt,
-			Vec<std::string>& sourceLines);
-
-		/// Used in std::sort
-		static bool compareStrings(const std::string& a, const std::string& b);
-
 		/// XXX
-		static const char* getTextFromGlType(GLenum dataType);
+		std::string createShaderProgSourceToCache(const std::string& source);
 };
 
 
@@ -263,18 +175,4 @@ inline bool Material2::isBlendingEnabled() const
 }
 
 
-/*inline const SProgAttribVar* Material2::getStandardAttributeVariable(
-	StandardAtributeVariables id) const
-{
-	return stdAttribVars[id];
-}
-
-
-inline const SProgUniVar* Material2::getStandardUniformVariable(
-	StandardUniformVariables id) const
-{
-	return stdUniVars[id];
-}*/
-
-
 #endif

+ 536 - 0
src/Resources/MaterialShaderProgramCreator.cpp

@@ -0,0 +1,536 @@
+#include "MaterialShaderProgramCreator.h"
+#include "Util/Scanner/Scanner.h"
+#include "Misc/Parser.h"
+#include "BuildinMaterialVariable.h"
+#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
+#include <boost/property_tree/ptree.hpp>
+
+
+//==============================================================================
+// Statics                                                                     =
+//==============================================================================
+
+boost::unordered_map<GLenum, const char*>
+MaterialShaderProgramCreator::glTypeToTxt = boost::assign::map_list_of
+	(GL_FLOAT, "float")
+	(GL_FLOAT_VEC2, "vec2")
+	(GL_FLOAT_VEC3, "vec3")
+	(GL_FLOAT_VEC4, "vec4")
+	(GL_SAMPLER_2D, "sampler2D")
+	(GL_FLOAT_MAT3, "mat3")
+	(GL_FLOAT_MAT4, "mat4")
+	(GL_NONE, "void");
+
+
+ConstCharPtrHashMap<GLenum>::Type MaterialShaderProgramCreator::txtToGlType =
+	boost::assign::map_list_of
+	("float", GL_FLOAT)
+	("vec2", GL_FLOAT_VEC2)
+	("vec3", GL_FLOAT_VEC3)
+	("vec4", GL_FLOAT_VEC4)
+	("sampler2D", GL_SAMPLER_2D)
+	("mat3", GL_FLOAT_MAT3)
+	("mat4", GL_FLOAT_MAT4)
+	("void", GL_NONE);
+
+
+boost::unordered_map<MaterialShaderProgramCreator::ArgQualifier, const char*>
+	MaterialShaderProgramCreator::argQualifierToTxt = boost::assign::map_list_of
+	(AQ_IN, "in")
+	(AQ_OUT, "out")
+	(AQ_INOUT, "inout");
+
+
+ConstCharPtrHashMap<MaterialShaderProgramCreator::ArgQualifier>::Type
+	MaterialShaderProgramCreator::txtToArgQualifier = boost::assign::map_list_of
+	("in", AQ_IN)
+	("out", AQ_OUT)
+	("inout", AQ_INOUT);
+
+
+const char* MaterialShaderProgramCreator::depthPassDefine = "DEPTH_PASS";
+
+
+//==============================================================================
+// Constructor                                                                 =
+//==============================================================================
+MaterialShaderProgramCreator::MaterialShaderProgramCreator(
+	const boost::property_tree::ptree& pt)
+{
+	parseShaderProgramTag(pt);
+}
+
+
+//==============================================================================
+// Destructor                                                                  =
+//==============================================================================
+MaterialShaderProgramCreator::~MaterialShaderProgramCreator()
+{}
+
+
+//==============================================================================
+// parseShaderFileForFunctionDefinitions                                       =
+//==============================================================================
+void MaterialShaderProgramCreator::parseShaderFileForFunctionDefinitions(
+	const char* filename)
+{
+	Scanner::Scanner scanner(filename, false);
+	const Scanner::Token* token = &scanner.getCrntToken();
+
+	// Forever
+	while(true)
+	{
+		getNextTokenAndSkipNewlines(scanner);
+		FuncDefinition* funcDef = NULL;
+
+		// EOF
+		if(token->getCode() == Scanner::TC_EOF)
+		{
+			break;
+		}
+		// #
+		else if(token->getCode() == Scanner::TC_SHARP)
+		{
+			parseUntilNewline(scanner);
+			continue;
+		}
+		// Return type
+		else if(token->getCode() == Scanner::TC_IDENTIFIER)
+		{
+			funcDef = new FuncDefinition;
+			funcDefs.push_back(funcDef);
+
+			try
+			{
+				funcDef->returnDataType =
+					txtToGlType.at(token->getValue().getString());
+			}
+			catch(std::exception& e)
+			{
+				throw PARSER_EXCEPTION("Unsupported type: " +
+					token->getValue().getString());
+			}
+
+			funcDef->returnDataTypeTxt = token->getValue().getString();
+		}
+		else
+		{
+			throw PARSER_EXCEPTION_EXPECTED("identifier");
+		}
+
+		// Function name
+		getNextTokenAndSkipNewlines(scanner);
+		if(token->getCode() != Scanner::TC_IDENTIFIER)
+		{
+			throw PARSER_EXCEPTION_EXPECTED("identifier");
+		}
+
+		funcDef->name = token->getValue().getString();
+
+		funcNameToDef[funcDef->name.c_str()] = funcDef;
+
+		// (
+		getNextTokenAndSkipNewlines(scanner);
+		if(token->getCode() != Scanner::TC_LPAREN)
+		{
+			throw PARSER_EXCEPTION_EXPECTED("(");
+		}
+
+		// Arguments
+		while(true)
+		{
+			ArgDefinition* argDef = new ArgDefinition;
+			funcDef->argDefinitions.push_back(argDef);
+
+			// Argument qualifier
+			getNextTokenAndSkipNewlines(scanner);
+			if(token->getCode() != Scanner::TC_IDENTIFIER)
+			{
+				throw PARSER_EXCEPTION_EXPECTED("identifier");
+			}
+
+			// For now accept only "in"
+			if(strcmp(token->getValue().getString(), "in"))
+			{
+				throw PARSER_EXCEPTION("Incorrect qualifier: " +
+					token->getValue().getString());
+			}
+
+			try
+			{
+				argDef->argQualifier = txtToArgQualifier.at(
+					token->getValue().getString());
+			}
+			catch(std::exception& e)
+			{
+				throw PARSER_EXCEPTION("Unsupported qualifier: " +
+					token->getValue().getString());
+			}
+
+			argDef->argQualifierTxt = token->getValue().getString();
+
+			// Type
+			getNextTokenAndSkipNewlines(scanner);
+			if(token->getCode() != Scanner::TC_IDENTIFIER)
+			{
+				throw PARSER_EXCEPTION_EXPECTED("identifier");
+			}
+
+			try
+			{
+				argDef->dataType = txtToGlType.at(
+					token->getValue().getString());
+			}
+			catch(std::exception& e)
+			{
+				throw PARSER_EXCEPTION("Unsupported type: " +
+					token->getValue().getString());
+			}
+
+			argDef->dataTypeTxt = token->getValue().getString();
+
+			// Name
+			getNextTokenAndSkipNewlines(scanner);
+			if(token->getCode() != Scanner::TC_IDENTIFIER)
+			{
+				throw PARSER_EXCEPTION_EXPECTED("identifier");
+			}
+
+			argDef->name = token->getValue().getString();
+
+			// ,
+			getNextTokenAndSkipNewlines(scanner);
+			if(token->getCode() == Scanner::TC_COMMA)
+			{
+				continue;
+			}
+			// )
+			else if(token->getCode() == Scanner::TC_RPAREN)
+			{
+				break;
+			}
+			else
+			{
+				throw PARSER_EXCEPTION_UNEXPECTED();
+			}
+		} // End arguments
+
+
+		// {
+		getNextTokenAndSkipNewlines(scanner);
+		if(token->getCode() != Scanner::TC_LBRACKET)
+		{
+			throw PARSER_EXCEPTION_EXPECTED("{");
+		}
+
+		// Skip until closing bracket
+		int bracketsNum = 0;
+		while(true)
+		{
+			getNextTokenAndSkipNewlines(scanner);
+
+			if(token->getCode() == Scanner::TC_RBRACKET)
+			{
+				if(bracketsNum == 0)
+				{
+					break;
+				}
+				--bracketsNum;
+			}
+			else if(token->getCode() == Scanner::TC_LBRACKET)
+			{
+				++bracketsNum;
+			}
+			else if(token->getCode() == Scanner::TC_EOF)
+			{
+				throw PARSER_EXCEPTION_UNEXPECTED();
+			}
+			else
+			{
+				continue;
+			}
+		} // End until closing bracket
+
+		/*std::stringstream ss;
+		ss << "Func def: " << funcDef->returnArg << " " << funcDef->name << " ";
+		BOOST_FOREACH(const ArgDefinition& adef, funcDef->argDefinitions)
+		{
+			ss << adef.callType << " " << adef.dataType << " " <<
+				adef.name << ", ";
+		}
+		std::cout << ss.str() << std::endl;*/
+	} // End for all functions
+}
+
+
+//==============================================================================
+// parseUntilNewline                                                           =
+//==============================================================================
+void MaterialShaderProgramCreator::parseUntilNewline(Scanner::Scanner& scanner)
+{
+	const Scanner::Token* token = &scanner.getCrntToken();
+	Scanner::TokenCode prevTc;
+
+	while(true)
+	{
+		prevTc = token->getCode();
+		scanner.getNextToken();
+
+		if(token->getCode() == Scanner::TC_EOF)
+		{
+			break;
+		}
+		else if(token->getCode() == Scanner::TC_NEWLINE &&
+			prevTc != Scanner::TC_BACK_SLASH)
+		{
+			break;
+		}
+	}
+}
+
+
+//==============================================================================
+// getNextTokenAndSkipNewlines                                                 =
+//==============================================================================
+void MaterialShaderProgramCreator::getNextTokenAndSkipNewlines(
+	Scanner::Scanner& scanner)
+{
+	const Scanner::Token* token;
+
+	while(true)
+	{
+		token = &scanner.getNextToken();
+		if(token->getCode() != Scanner::TC_NEWLINE)
+		{
+			break;
+		}
+	}
+}
+
+
+//==============================================================================
+// parseShaderProgramTag                                                       =
+//==============================================================================
+void MaterialShaderProgramCreator::parseShaderProgramTag(
+	const boost::property_tree::ptree& pt)
+{
+	using namespace boost::property_tree;
+
+	srcLines.push_back("#pragma anki start vertexShader");
+	srcLines.push_back("#pragma anki include \"shaders/MaterialVert.glsl\"");
+	srcLines.push_back("#pragma anki start fragmentShader");
+
+	//
+	// <includes></includes>
+	//
+	boost::ptr_vector<FuncDefinition> funcDefs;
+	Vec<std::string> includeLines;
+
+	const ptree& includesPt = pt.get_child("includes");
+	BOOST_FOREACH(const ptree::value_type& v, includesPt)
+	{
+		if(v.first != "include")
+		{
+			throw EXCEPTION("Expected include and not: " + v.first);
+		}
+
+		const std::string& fname = v.second.data();
+		parseShaderFileForFunctionDefinitions(fname.c_str());
+
+		includeLines.push_back("#pragma anki include \"" + fname + "\"");
+	}
+
+	std::sort(includeLines.begin(), includeLines.end(), compareStrings);
+	srcLines.insert(srcLines.end(), includeLines.begin(), includeLines.end());
+
+	//
+	// <ins></ins>
+	//
+	Vec<std::string> uniformsLines; // Store the source of the uniform vars
+
+	boost::optional<const ptree&> insPt = pt.get_child_optional("ins");
+	if(insPt)
+	{
+		BOOST_FOREACH(const ptree::value_type& v, insPt.get())
+		{
+			if(v.first != "in")
+			{
+				throw EXCEPTION("Expected in and not: " + v.first);
+			}
+
+			const ptree& inPt = v.second;
+			std::string line;
+			parseInTag(inPt, line);
+			uniformsLines.push_back(line);
+		} // end for all ins
+
+		srcLines.push_back("");
+		std::sort(uniformsLines.begin(), uniformsLines.end(), compareStrings);
+		srcLines.insert(srcLines.end(), uniformsLines.begin(),
+			uniformsLines.end());
+	}
+
+	//
+	// <operators></operators>
+	//
+	srcLines.push_back("\n#pragma anki include "
+		"\"shaders/MaterialFragmentVariables.glsl\"\n"
+		"\nvoid main()\n{");
+
+	const ptree& opsPt = pt.get_child("operators");
+
+	BOOST_FOREACH(const ptree::value_type& v, opsPt)
+	{
+		if(v.first != "operator")
+		{
+			throw EXCEPTION("Expected operator and not: " + v.first);
+		}
+
+		const ptree& opPt = v.second;
+		parseOperatorTag(opPt);
+	} // end for all operators
+
+	srcLines.push_back("}\n");
+
+	//
+	// Create the output
+	//
+	BOOST_FOREACH(const std::string& line, srcLines)
+	{
+		source += line + "\n";
+	}
+
+	//std::cout << source << std::endl;
+}
+
+
+//==============================================================================
+// parseInTag                                                                  =
+//==============================================================================
+void MaterialShaderProgramCreator::parseInTag(
+	const boost::property_tree::ptree& pt, std::string& line)
+{
+	using namespace boost::property_tree;
+
+	const std::string& name = pt.get<std::string>("name");
+	boost::optional<const ptree&> valuePt = pt.get_child_optional("value");
+
+	line = "uniform ";
+
+	// Buildin
+	if(!valuePt)
+	{
+		BuildinMaterialVariable::BuildinVariable tmp;
+		GLenum dataType;
+
+		if(!BuildinMaterialVariable::isBuildin(name.c_str(), &tmp, &dataType))
+		{
+			throw EXCEPTION("The variable is not build in: " + name);
+		}
+
+		boost::unordered_map<GLenum, const char*>::const_iterator it =
+			glTypeToTxt.find(dataType);
+
+		ASSERT(it != glTypeToTxt.end() &&
+			"Buildin's type is not registered");
+
+		line += it->second;
+	}
+	else
+	{
+		if(valuePt.get().size() != 1)
+		{
+			throw EXCEPTION("Bad value for in: " + name);
+		}
+
+		const ptree::value_type& v = valuePt.get().front();
+
+		// Wrong tag
+		if(txtToGlType.find(v.first.c_str()) == txtToGlType.end())
+		{
+			throw EXCEPTION("Wrong type \"" + v.first + "\" for in: " +
+				name);
+		}
+
+		line += v.first;
+	}
+
+	line += " " + name + ";";
+}
+
+
+//==============================================================================
+// parseOperatorTag                                                            =
+//==============================================================================
+void MaterialShaderProgramCreator::parseOperatorTag(
+	const boost::property_tree::ptree& pt)
+{
+	using namespace boost::property_tree;
+
+	int id = pt.get<int>("id");
+	const std::string& funcName = pt.get<std::string>("function");
+	const ptree& argsPt = pt.get_child("arguments");
+	std::stringstream line;
+
+	// Find func def
+	ConstCharPtrHashMap<FuncDefinition*>::Type::const_iterator it =
+		funcNameToDef.find(funcName.c_str());
+
+	if(it == funcNameToDef.end())
+	{
+		throw EXCEPTION("Function is not defined in any include file: " +
+			funcName);
+	}
+
+	const FuncDefinition* def = it->second;
+
+	// Check args size
+	if(argsPt.size() != def->argDefinitions.size())
+	{
+		throw EXCEPTION("Incorrect number of arguments for: " + funcName);
+	}
+
+	// Write return value
+	if(def->returnDataType != GL_NONE)
+	{
+		line << def->returnDataTypeTxt << " operatorOut" << id << " = ";
+	}
+
+	// Func name
+	line << funcName + "(";
+
+	// Write all arguments
+	size_t i = 0;
+	BOOST_FOREACH(const ptree::value_type& v, argsPt)
+	{
+		if(v.first != "argument")
+		{
+			throw EXCEPTION("Unexpected tag \"" + v.first +
+				"\" for operator: " + boost::lexical_cast<std::string>(id));
+
+		}
+
+		line << v.second.data();
+
+		// Add a comma
+		++i;
+		if(i != argsPt.size())
+		{
+			line << ", ";
+		}
+	}
+	line << ");";
+
+	srcLines.push_back("\t" + line.str());
+}
+
+
+//==============================================================================
+// compareStrings                                                              =
+//==============================================================================
+bool MaterialShaderProgramCreator::compareStrings(
+	const std::string& a, const std::string& b)
+{
+	return a < b;
+}

+ 129 - 0
src/Resources/MaterialShaderProgramCreator.h

@@ -0,0 +1,129 @@
+#ifndef MATERIAL_SHADER_PROGRAM_CREATOR_H
+#define MATERIAL_SHADER_PROGRAM_CREATOR_H
+
+#include "Util/ConstCharPtrHashMap.h"
+#include "Util/Vec.h"
+#include <GL/glew.h>
+#include <boost/property_tree/ptree_fwd.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+
+
+namespace Scanner {
+class Scanner;
+}
+
+
+/// XXX
+class MaterialShaderProgramCreator
+{
+	public:
+		MaterialShaderProgramCreator(const boost::property_tree::ptree& pt);
+		~MaterialShaderProgramCreator();
+
+		/// XXX
+		const std::string& getShaderProgramSource() const {return source;}
+
+		/// XXX
+		static const char* getDepthPassDefine() {return depthPassDefine;}
+
+	private:
+		//======================================================================
+		// Nested                                                              =
+		//======================================================================
+
+		/// Function argument data call type
+		enum ArgQualifier
+		{
+			AQ_IN,
+			AQ_OUT,
+			AQ_INOUT
+		};
+
+		/// Function argument definition
+		struct ArgDefinition
+		{
+			ArgQualifier argQualifier;
+			std::string argQualifierTxt;
+			GLenum dataType;
+			std::string dataTypeTxt;
+			std::string name;
+		};
+
+		/// Function definition. It contains information about a function (eg
+		/// return type and the arguments)
+		struct FuncDefinition
+		{
+			std::string name; ///< Function name
+			boost::ptr_vector<ArgDefinition> argDefinitions;
+			GLenum returnDataType;
+			std::string returnDataTypeTxt;
+		};
+
+		//======================================================================
+		// Members                                                             =
+		//======================================================================
+
+		/// Go from enum GL_SOMETHING to "GL_SOMETHING" string
+		static boost::unordered_map<GLenum, const char*> glTypeToTxt;
+
+		/// Go from "GL_SOMETHING" string to GL_SOMETHING enum
+		static ConstCharPtrHashMap<GLenum>::Type txtToGlType;
+
+		/// Go from enum AQ_SOMETHING to "AQ_SOMETHING" string
+		static boost::unordered_map<ArgQualifier, const char*>
+			argQualifierToTxt;
+
+		/// Go from "AQ_SOMETHING" string to AQ_SOMETHING enum
+		static ConstCharPtrHashMap<ArgQualifier>::Type txtToArgQualifier;
+
+		/// Container that holds the function definitions
+		boost::ptr_vector<FuncDefinition> funcDefs;
+
+		/// Go from funtion name to function definition
+		ConstCharPtrHashMap<FuncDefinition*>::Type funcNameToDef;
+
+		Vec<std::string> srcLines; ///< The lines of the shader program source
+
+		std::string source; ///< Shader program final source
+
+		static const char* depthPassDefine; ///< XXX
+
+		//======================================================================
+		// Methods                                                             =
+		//======================================================================
+
+		/// Parses a glsl file for function definitions. It appends the
+		/// funcDefs container with new function definitions
+		void parseShaderFileForFunctionDefinitions(const char* filename);
+
+		/// Used by parseShaderFileForFunctionDefinitions to skip preprocessor
+		/// definitions. Takes into account the backslashes. For example for
+		/// @code
+		/// #define lala \
+		/// 	10
+		/// @endcode
+		/// it skips from define to 10
+		static void parseUntilNewline(Scanner::Scanner& scanner);
+
+		/// It being used by parseShaderFileForFunctionDefinitions and it
+		/// skips until newline after a '#' found. It takes into account the
+		/// back slashes that the preprocessor may have
+		static void getNextTokenAndSkipNewlines(Scanner::Scanner& scanner);
+
+		/// Used for shorting vectors of strings. Used in std::sort
+		static bool compareStrings(const std::string& a, const std::string& b);
+
+		/// Parse what is within the
+		/// @code <shaderProgram></shaderProgram> @endcode
+		void parseShaderProgramTag(const boost::property_tree::ptree& pt);
+
+		/// Parse what is within the @code <in></in> @endcode
+		static void parseInTag(const boost::property_tree::ptree& pt,
+			std::string& line);
+
+		/// Parse what is within the @code <operation></operation> @endcode
+		void parseOperatorTag(const boost::property_tree::ptree& pt);
+};
+
+
+#endif

+ 3 - 1
src/Resources/SProgUniVar.cpp

@@ -1,6 +1,7 @@
 #include "SProgUniVar.h"
 #include "Resources/ShaderProg.h"
 #include "Resources/Texture.h"
+#include "GfxApi/GlStateMachine.h"
 
 
 //==============================================================================
@@ -12,7 +13,8 @@
 /// - if the GL driver gives the same location as the one the var has
 #define STD_SET_UNI_CHECK() \
 	ASSERT(getLoc() != -1); \
-	ASSERT(ShaderProg::getCurrentProgramGlId() == getFatherSProg().getGlId()); \
+	ASSERT(GlStateMachineSingleton::getInstance().getCurrentProgramGlId() == \
+		getFatherSProg().getGlId()); \
 	ASSERT(glGetUniformLocation(getFatherSProg().getGlId(), \
 		getName().c_str()) == getLoc());
 

+ 12 - 11
src/Resources/ShaderProg.h

@@ -4,7 +4,7 @@
 #include <boost/ptr_container/ptr_vector.hpp>
 #include <GL/glew.h>
 #include <limits>
-#include "Util/CharPtrHashMap.h"
+#include "Util/ConstCharPtrHashMap.h"
 #include "Util/Assert.h"
 #include "SProgUniVar.h"
 #include "SProgAttribVar.h"
@@ -32,8 +32,8 @@ class ShaderProg
 		/// @name Accessors
 		/// @{
 		GLuint getGlId() const;
-		GETTER_R(boost::ptr_vector<SProgUniVar>, uniVars, getUniVars)
-		GETTER_R(boost::ptr_vector<SProgAttribVar>, attribVars, getAttribVars)
+		/*GETTER_R(boost::ptr_vector<SProgUniVar>, uniVars, getUniVars)
+		GETTER_R(boost::ptr_vector<SProgAttribVar>, attribVars, getAttribVars)*/
 		/// @}
 
 		/// Resource load
@@ -43,11 +43,11 @@ class ShaderProg
 		void bind() const;
 		
 		/// Unbind all shader programs
-		static void unbind() {glUseProgram(0);}
+		//static void unbind() {glUseProgram(0);}
 
 		/// Query the GL driver for the current shader program GL ID
 		/// @return Shader program GL id
-		static uint getCurrentProgramGlId();
+		//static uint getCurrentProgramGlId();
 
 		/// Find uniform variable. On failure it throws an exception so use
 		/// @ref uniVarExists to check if var exists
@@ -87,10 +87,10 @@ class ShaderProg
 
 	private:
 		/// Uniform variable name to variable iterator
-		typedef CharPtrHashMap<SProgUniVar*>::const_iterator
+		typedef ConstCharPtrHashMap<SProgUniVar*>::Type::const_iterator
 			NameToSProgUniVarIterator;
 		/// Attribute variable name to variable iterator
-		typedef CharPtrHashMap<SProgAttribVar*>::const_iterator
+		typedef ConstCharPtrHashMap<SProgAttribVar*>::Type::const_iterator
 			NameToSProgAttribVarIterator;
 
 		std::string rsrcFilename;
@@ -105,8 +105,9 @@ class ShaderProg
 		/// All the attribute variables
 		boost::ptr_vector<SProgAttribVar> attribVars;
 		/// A UnorderedMap for fast variable searching
-		CharPtrHashMap<SProgUniVar*> uniNameToVar;
-		CharPtrHashMap<SProgAttribVar*> attribNameToVar; ///< @see uniNameToVar
+		ConstCharPtrHashMap<SProgUniVar*>::Type uniNameToVar;
+		///< @see uniNameToVar
+		ConstCharPtrHashMap<SProgAttribVar*>::Type attribNameToVar;
 
 		/// Query the driver to get the vars. After the linking of the shader
 		/// prog is done gather all the vars in custom containers
@@ -147,12 +148,12 @@ inline void ShaderProg::bind() const
 }
 
 
-inline uint ShaderProg::getCurrentProgramGlId()
+/*inline uint ShaderProg::getCurrentProgramGlId()
 {
 	int i;
 	glGetIntegerv(GL_CURRENT_PROGRAM, &i);
 	return i;
-}
+}*/
 
 
 #endif

+ 3 - 3
src/Scene/MaterialRuntime.cpp

@@ -29,7 +29,7 @@ MaterialRuntime::MaterialRuntime(const Material& mtl_):
 MaterialRuntimeUserDefinedVar& MaterialRuntime::getUserDefinedVarByName(
 	const char* name)
 {
-	CharPtrHashMap<MaterialRuntimeUserDefinedVar*>::iterator it =
+	ConstCharPtrHashMap<MaterialRuntimeUserDefinedVar*>::Type::iterator it =
 		userDefVarsHashMap.find(name);
 	if(it == userDefVarsHashMap.end())
 	{
@@ -46,8 +46,8 @@ MaterialRuntimeUserDefinedVar& MaterialRuntime::getUserDefinedVarByName(
 const MaterialRuntimeUserDefinedVar& MaterialRuntime::getUserDefinedVarByName(
 	const char* name) const
 {
-	CharPtrHashMap<MaterialRuntimeUserDefinedVar*>::const_iterator it =
-		userDefVarsHashMap.find(name);
+	ConstCharPtrHashMap<MaterialRuntimeUserDefinedVar*>::Type::const_iterator
+		it = userDefVarsHashMap.find(name);
 	if(it == userDefVarsHashMap.end())
 	{
 		throw EXCEPTION("Cannot get user defined variable with name \"" +

+ 3 - 2
src/Scene/MaterialRuntime.h

@@ -4,7 +4,7 @@
 #include <boost/ptr_container/ptr_vector.hpp>
 #include "MaterialRuntimeUserDefinedVar.h"
 #include "Util/Accessors.h"
-#include "Util/CharPtrHashMap.h"
+#include "Util/ConstCharPtrHashMap.h"
 #include "Resources/Material.h"
 
 
@@ -76,7 +76,8 @@ class MaterialRuntime: private MaterialProps
 		const Material& mtl; ///< The resource
 		MaterialRuntimeUserDefinedVarContainer userDefVars;
 		/// For fast finding the variables
-		CharPtrHashMap<MaterialRuntimeUserDefinedVar*> userDefVarsHashMap;
+		ConstCharPtrHashMap<MaterialRuntimeUserDefinedVar*>::Type
+			userDefVarsHashMap;
 };
 
 

+ 0 - 40
src/Util/CharPtrHashMap.h

@@ -1,40 +0,0 @@
-#ifndef CHAR_PTR_HASH_MAP_H
-#define CHAR_PTR_HASH_MAP_H
-
-#include <boost/unordered_map.hpp>
-#include <cstring>
-
-
-/// The hash function
-struct CreateCharPtrHashMapKey
-{
-	size_t operator()(const char* str) const
-	{
-		size_t h = 0;
-		for (; *str != '\0'; ++str)
-		{
-			h += *str;
-		}
-		return h;
-	}
-};
-
-
-/// The collision evaluation function
-struct CompareCharPtrHashMapKeys
-{
-  bool operator()(const char* a, const char* b) const
-  {
-    return strcmp(a, b) == 0;
-  }
-};
-
-
-/// The hash map that has as key an old school C string. When inserting the char MUST NOT point to a temporary or the
-/// evaluation function will fail.
-template<typename Type>
-class CharPtrHashMap: public boost::unordered_map<const char*, Type, CreateCharPtrHashMapKey, CompareCharPtrHashMapKeys>
-{};
-
-
-#endif

+ 44 - 0
src/Util/ConstCharPtrHashMap.h

@@ -0,0 +1,44 @@
+#ifndef CONST_CHAR_PTR_HASH_MAP_H
+#define CONST_CHAR_PTR_HASH_MAP_H
+
+#include <boost/unordered_map.hpp>
+#include <cstring>
+
+
+/// The hash function
+struct CreateCharPtrHashMapKey
+{
+	size_t operator()(const char* str) const
+	{
+		size_t h = 0;
+		for (; *str != '\0'; ++str)
+		{
+			h += *str;
+		}
+		return h;
+	}
+};
+
+
+/// The collision evaluation function
+struct CompareCharPtrHashMapKeys
+{
+	bool operator()(const char* a, const char* b) const
+	{
+		return strcmp(a, b) == 0;
+	}
+};
+
+
+/// The hash map that has as key an old school C string. When inserting the
+/// char MUST NOT point to a temporary or the evaluation function will fail.
+/// Its template struct because C++ does not offer template typedefs
+template<typename T>
+struct ConstCharPtrHashMap
+{
+	typedef boost::unordered_map<const char*, T,
+		CreateCharPtrHashMapKey, CompareCharPtrHashMapKeys> Type;
+};
+
+
+#endif