Pārlūkot izejas kodu

- Adding a convenience class (StringList)
- Modyfing the material (WIP)
- Finalizung the material format

Wont compile

Panagiotis Christopoulos Charitos 14 gadi atpakaļ
vecāks
revīzija
cb7a6b7b10

+ 4 - 4
anki/resource/Image.cpp

@@ -1,10 +1,10 @@
+#include "anki/resource/Image.h"
+#include "anki/util/Exception.h"
+#include "anki/core/Logger.h"
 #include <png.h>
 #include <boost/filesystem.hpp> // For file extensions
 #include <boost/algorithm/string.hpp> // For to_lower
 #include <fstream>
-#include "anki/resource/Image.h"
-#include "anki/util/Exception.h"
-#include "anki/core/Logger.h"
 
 
 namespace anki {
@@ -86,7 +86,7 @@ void Image::loadCompressedTga(std::fstream& fs, uint& bpp)
 	uint pixelcount = height * width;
 	uint currentpixel = 0;
 	uint currentbyte = 0;
-	unsigned char colorbuffer[4];
+	uchar colorbuffer[4];
 
 	do
 	{

+ 1 - 24
anki/resource/Material.cpp

@@ -40,33 +40,16 @@ ConstCharPtrHashMap<GLenum>::Type Material::txtToBlengGlEnum =
 	TXT_AND_ENUM(GL_ONE_MINUS_SRC_COLOR);
 
 
-//==============================================================================
-// Constructor                                                                 =
 //==============================================================================
 Material::Material()
-{
-	renderInBlendingStageFlag = false;
-	blendingSfactor = GL_ONE;
-	blendingDfactor = GL_ZERO;
-	depthTesting = true;
-	wireframe = false;
-	castsShadowFlag = true;
-
-	// Reset tha array
-	std::fill(buildinsArr.begin(), buildinsArr.end(),
-		static_cast<MaterialBuildinVariable*>(NULL));
-}
+{}
 
 
-//==============================================================================
-// Destructor                                                                  =
 //==============================================================================
 Material::~Material()
 {}
 
 
-//==============================================================================
-// load                                                                        =
 //==============================================================================
 void Material::load(const char* filename)
 {
@@ -85,8 +68,6 @@ void Material::load(const char* filename)
 }
 
 
-//==============================================================================
-// parseMaterialTag                                                            =
 //==============================================================================
 void Material::parseMaterialTag(const boost::property_tree::ptree& pt)
 {
@@ -191,8 +172,6 @@ void Material::parseMaterialTag(const boost::property_tree::ptree& pt)
 }
 
 
-//==============================================================================
-// createShaderProgSourceToCache                                               =
 //==============================================================================
 std::string Material::createShaderProgSourceToCache(const std::string& source)
 {
@@ -225,8 +204,6 @@ std::string Material::createShaderProgSourceToCache(const std::string& source)
 }
 
 
-//==============================================================================
-// populateVariables                                                           =
 //==============================================================================
 void Material::populateVariables(const boost::property_tree::ptree& pt)
 {

+ 32 - 70
anki/resource/Material.h

@@ -52,17 +52,19 @@ class ShaderProgram;
 /// 	[<wireframe>true | false</wireframe>] (2)
 ///
 /// 	<shaderProgram>
-/// 		<vertexShader>
-/// 			<includes> (5)
-/// 				<functionsFile>file.glsl</functionsFile>
-/// 				<codeFile>file2.glsl</codeFile>
+/// 		<shader> (5)
+/// 			<type>vertex | tc | te | geometry | fragment</type>
+///
+/// 			<includes>
+/// 				<include>path/to/file.glsl</include>
+/// 				<include>path/to/file2.glsl</include>
 /// 			</includes>
 ///
-/// 			[<inputs> (3)
+/// 			[<inputs> (4)
 /// 				<input>
 /// 					<name>xx</name>
-/// 					<type>any_glsl_accepted_type</type>
-/// 					[<value> (4)
+/// 					<type>any glsl type</type>
+/// 					[<value> (3)
 /// 						a_series_of_numbers |
 /// 						path/to/image.tga
 /// 					</value>]
@@ -72,16 +74,17 @@ class ShaderProgram;
 /// 			<operations>
 /// 				<operation>
 /// 					<id>x</id>
+/// 					[<returnType>any glsl type</returnType>]
 /// 					<function>functionName</function>
-/// 					<arguments>
+/// 					[<arguments>
 /// 						<argument>xx</argument>
 /// 						<argument>yy</argument>
-/// 					</arguments>
+/// 					</arguments>]
 /// 				</operation>
 /// 			</operations>
 /// 		</vertexShader>
 ///
-/// 		<fragmentShader>...</fragmentShader>
+/// 		<shader>...</shader>
 /// 	</shaderProgram>
 /// </material>
 /// @endcode
@@ -89,13 +92,11 @@ class ShaderProgram;
 ///
 /// (2): Not relevant for light materials at the moment
 ///
-/// (3): AKA uniforms
+/// (3): The \<value\> tag is not present for build-in variables
 ///
-/// (4): The <value> tag is not present for build-in variables
+/// (4): AKA uniforms
 ///
-/// (5): functionsFile means that the file contains only function declarations
-/// and the parser will expect only those. The codeFile means that the file
-/// may contain anything and will not get parsed
+/// (5): The order of the shaders is crucial
 class Material: public MaterialProperties
 {
 	public:
@@ -105,52 +106,15 @@ class Material: public MaterialProperties
 
 		typedef boost::ptr_vector<MaterialVariable> VarsContainer;
 
-		typedef boost::unordered_map<MaterialBuildinVariable::MatchingVariable,
-			MaterialBuildinVariable*> MatchingVariableToBuildinHashMap;
-
-		typedef boost::array<MaterialBuildinVariable*,
-			MaterialBuildinVariable::MV_NUM> BuildinsArr;
-
 		//======================================================================
 		// Methods                                                             =
 		//======================================================================
 
-		/// Initialize with default values
 		Material();
-
 		~Material();
 
 		/// @name Accessors
 		/// @{
-		bool getCastShadow() const
-		{
-			return castsShadowFlag;
-		}
-
-		bool getRendersInBlendingStage() const
-		{
-			return renderInBlendingStageFlag;
-		}
-
-		int getBlendingSfactor() const
-		{
-			return blendingSfactor;
-		}
-
-		int getBlendingDfactor() const
-		{
-			return blendingDfactor;
-		}
-
-		bool getGetDepthTesting() const
-		{
-			return depthTesting;
-		}
-
-		bool getWireframe() const
-		{
-			return wireframe;
-		}
 
 		/// Access the base class just for copying in other classes
 		const MaterialProperties& getBaseClass() const
@@ -158,9 +122,9 @@ class Material: public MaterialProperties
 			return *this;
 		}
 
-		const ShaderProgram& getShaderProgram(PassType p) const
+		const ShaderProgram& getShaderProgram(uint pass, uint level) const
 		{
-			return *sProgs[p];
+			return *eSProgs[pass][level];
 		}
 
 		// Variable accessors
@@ -209,9 +173,14 @@ class Material: public MaterialProperties
 		//======================================================================
 		// Nested                                                              =
 		//======================================================================
-
-		typedef boost::array<ShaderProgramResourcePointer, PASS_TYPES_NUM>
-			ShaderPrograms;
+		
+		/// Type for garbage collection
+		typedef boost::ptr_vector<ShaderProgramResourcePointer> ShaderPrograms;
+		
+		/// Type for easy accessing the shader programs. Its a 2D array with 
+		/// the first dimention the pass ID and the second the level of detail
+		typedef std::vector<std::vector<ShaderProgram*> > EasyShaderPrograms;
+		
 
 		//======================================================================
 		// Members                                                             =
@@ -225,12 +194,13 @@ class Material: public MaterialProperties
 		/// All the material variables. Both buildins and user
 		VarsContainer mtlVars;
 
-		BuildinsArr buildinsArr; ///< To find. Initialize to int
-
-		std::vector<MaterialUserVariable*> userMtlVars; ///< To iterate
-
-		/// The most important aspect of materials
+		/// The most important aspect of materials. These are all the shader 
+		/// programs per level and per pass. Their number are NP * NL where
+		/// NP is the number of passes and NL the number of levels of detail
 		ShaderPrograms sProgs;
+		
+		/// Easy access the shader programs
+		EasyShaderPrograms eSProgs;
 
 		//======================================================================
 		// Methods                                                             =
@@ -247,14 +217,6 @@ class Material: public MaterialProperties
 };
 
 
-inline const MaterialBuildinVariable& Material::getBuildinVariable(
-	MaterialBuildinVariable::MatchingVariable e) const
-{
-	ANKI_ASSERT(buildinVariableExits(e));
-	return *buildinsArr[e];
-}
-
-
 } // end namespace
 
 

+ 71 - 8
anki/resource/MaterialProperties.h

@@ -1,30 +1,93 @@
 #ifndef ANKI_RESOURCE_MATERIAL_PROPERTIES_H
 #define ANKI_RESOURCE_MATERIAL_PROPERTIES_H
 
+#include "anki/util/StringList.h"
 #include <GL/glew.h>
 
 
 namespace anki {
 
 
-/// Contains a few properties that other classes may use
+/// Contains a few properties that other classes may use. For an explanation of
+/// the variables refer to Material class documentation
 struct MaterialProperties
 {
 	public:
+		/// Initialize with default values
+		MaterialProperties()
+		{
+			renderingStage = 0;
+			levelsOfDetail = 1;
+			shadow = false;
+			blendingSfactor = GL_ONE;
+			blendingDfactor = GL_ZERO;
+			depthTesting = true;
+			wireframe = false;
+		}
+		
+		/// @name Accessors
+		/// @{
+		uint getRenderingStage() const
+		{
+			return renderingStage;
+		}
+		
+		const StringList& getPasses() const
+		{
+			return passes;
+		}
+		
+		uint getLevelsOfDetail() const
+		{
+			return levelsOfDetail;
+		}
+		
+		bool getShadow() const
+		{
+			return shadow;
+		}
+
+		int getBlendingSfactor() const
+		{
+			return blendingSfactor;
+		}
+
+		int getBlendingDfactor() const
+		{
+			return blendingDfactor;
+		}
+
+		bool getGetDepthTesting() const
+		{
+			return depthTesting;
+		}
+
+		bool getWireframe() const
+		{
+			return wireframe;
+		}
+		/// @}
+		
 		/// Check if blending is enabled
 		bool isBlendingEnabled() const
-			{return blendingSfactor != GL_ONE || blendingDfactor != GL_ZERO;}
+		{
+			return blendingSfactor != GL_ONE || blendingDfactor != GL_ZERO;
+		}
 
 	protected:
-		/// Used in depth passes of shadowmapping and not in other depth passes
-		/// like EarlyZ
-		bool castsShadowFlag;
-		/// The entities with blending are being rendered in blending stage and
-		/// those without in material stage
-		bool renderInBlendingStageFlag;
+		uint renderingStage;
+		
+		StringList passes;
+		
+		uint levelsOfDetail;
+	
+		bool shadow;
+		
 		int blendingSfactor; ///< Default GL_ONE
 		int blendingDfactor; ///< Default GL_ZERO
+		
 		bool depthTesting;
+		
 		bool wireframe;
 };
 

+ 66 - 547
anki/resource/MaterialShaderProgramCreator.cpp

@@ -1,8 +1,4 @@
 #include "anki/resource/MaterialShaderProgramCreator.h"
-#include "anki/util/scanner/Scanner.h"
-#include "anki/misc/Parser.h"
-#include "anki/resource/MaterialBuildinVariable.h"
-#include <boost/assign/list_of.hpp>
 #include <boost/foreach.hpp>
 #include <boost/property_tree/ptree.hpp>
 
@@ -10,60 +6,6 @@
 namespace anki {
 
 
-//==============================================================================
-// 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);
-
-
-ConstCharPtrHashMap<GLenum>::Type
-	MaterialShaderProgramCreator::varyingNameToGlType =
-	boost::assign::map_list_of
-	("vTexCoords", GL_FLOAT_VEC2)
-	("vNormal", GL_FLOAT_VEC3)
-	("vTangent", GL_FLOAT_VEC3)
-	("vTangentW", GL_FLOAT)
-	("vVertPosViewSpace", GL_FLOAT_VEC3);
-
-
-//==============================================================================
-// Constructor                                                                 =
 //==============================================================================
 MaterialShaderProgramCreator::MaterialShaderProgramCreator(
 	const boost::property_tree::ptree& pt)
@@ -72,264 +14,30 @@ MaterialShaderProgramCreator::MaterialShaderProgramCreator(
 }
 
 
-//==============================================================================
-// Destructor                                                                  =
 //==============================================================================
 MaterialShaderProgramCreator::~MaterialShaderProgramCreator()
 {}
 
 
 //==============================================================================
-// parseShaderFileForFunctionDefinitions                                       =
-//==============================================================================
-void MaterialShaderProgramCreator::parseShaderFileForFunctionDefinitions(
-	const char* filename,
-	boost::ptr_vector<FuncDefinition>& funcDefs,
-	ConstCharPtrHashMap<FuncDefinition*>::Type& funcNameToDef)
-{
-	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_END)
-		{
-			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_L_PAREN)
-		{
-			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");
-			}
-
-			/*if(token->getValue().getString() == std::string("lowp") ||
-				token->getValue().getString() == std::string("highp") ||
-				token->getValue().getString() == std::string("mediump"))
-			{
-				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_R_PAREN)
-			{
-				break;
-			}
-			else
-			{
-				throw PARSER_EXCEPTION_UNEXPECTED();
-			}
-		} // End arguments
-
-
-		// {
-		getNextTokenAndSkipNewlines(scanner);
-		if(token->getCode() != scanner::TC_L_BRACKET)
-		{
-			throw PARSER_EXCEPTION_EXPECTED("{");
-		}
-
-		// Skip until closing bracket
-		int bracketsNum = 0;
-		while(true)
-		{
-			getNextTokenAndSkipNewlines(scanner);
-
-			if(token->getCode() == scanner::TC_R_BRACKET)
-			{
-				if(bracketsNum == 0)
-				{
-					break;
-				}
-				--bracketsNum;
-			}
-			else if(token->getCode() == scanner::TC_L_BRACKET)
-			{
-				++bracketsNum;
-			}
-			else if(token->getCode() == scanner::TC_END)
-			{
-				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)
+void MaterialShaderProgramCreator::parseShaderProgramTag(
+	const boost::property_tree::ptree& pt)
 {
-	const scanner::Token* token = &scanner.getCrntToken();
-	scanner::TokenCode prevTc;
+	using namespace boost::property_tree;
 
-	while(true)
+	BOOST_FOREACH(const ptree::value_type& v, pt)
 	{
-		prevTc = token->getCode();
-		scanner.getNextToken();
-
-		if(token->getCode() == scanner::TC_END)
-		{
-			break;
-		}
-		else if(token->getCode() == scanner::TC_NEWLINE &&
-			prevTc != scanner::TC_BACK_SLASH)
+		if(v.first != "shader")
 		{
-			break;
+			throw ANKI_EXCEPTION("Expected \"shader\" tag and not: " + 
+				v.first);
 		}
+		
+		parseShaderTag(v.second);
 	}
-}
-
-
-//==============================================================================
-// getNextTokenAndSkipNewlines                                                 =
-//==============================================================================
-void MaterialShaderProgramCreator::getNextTokenAndSkipNewlines(
-	scanner::Scanner& scanner)
-{
-	const scanner::Token* token;
 
-	while(true)
-	{
-		token = &scanner.getNextToken();
-		if(token->getCode() != scanner::TC_NEWLINE)
-		{
-			break;
-		}
-	}
+	srcLines.join("\n", source);
+	//std::cout << source << std::endl;
 }
 
 
@@ -338,101 +46,14 @@ void MaterialShaderProgramCreator::parseShaderTag(
 	const boost::property_tree::ptree& pt)
 {
 	//
-	// <includes></includes>
-	//
-	boost::ptr_vector<FuncDefinition> funcDefs;
-	ConstCharPtrHashMap<FuncDefinition*>::Type funcNameToDef;
-	std::vector<std::string> includeLines;
-
-	const ptree& includesPt = pt.get_child("includes");
-	BOOST_FOREACH(const ptree::value_type& v, includesPt)
-	{
-		if(v.first != "include")
-		{
-			throw ANKI_EXCEPTION("Expected include and not: " + v.first);
-		}
-
-		const std::string& fname = v.second.data();
-		parseShaderFileForFunctionDefinitions(fname.c_str(),
-			funcDefs, funcNameToDef);
-
-		includeLines.push_back("#pragma anki include \"" + fname + "\"");
-	}
-
-	std::sort(includeLines.begin(), includeLines.end(), compareStrings);
-	srcLines.insert(srcLines.end(), includeLines.begin(), includeLines.end());
-
-	//
-	// <inputs></inputs>
-	//
-
-	// Store the source of the uniform vars
-	std::vector<std::string> uniformsLines;
-
-	boost::optional<const ptree&> insPt = pt.get_child_optional("inputs");
-	if(insPt)
-	{
-		BOOST_FOREACH(const ptree::value_type& v, insPt.get())
-		{
-			if(v.first != "input")
-			{
-				throw ANKI_EXCEPTION("Expected <input> and not: " + v.first);
-			}
-
-			const ptree& inPt = v.second;
-			std::string line;
-			parseInputTag(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());
-	}
-
-	//
-	// <operations></operations>
+	// <type></type>
 	//
-	srcLines.push_back("\nvoid main()\n{");
-
-	const ptree& opsPt = pt.get_child("operations");
-
-	BOOST_FOREACH(const ptree::value_type& v, opsPt)
-	{
-		if(v.first != "operation")
-		{
-			throw ANKI_EXCEPTION("Expected operation and not: " + v.first);
-		}
-
-		const ptree& opPt = v.second;
-		parseOperatorTag(opPt);
-	} // end for all operations
-
-	srcLines.push_back("}\n");
-}
-
-
-//==============================================================================
-// parseShaderProgramTag                                                       =
-//==============================================================================
-void MaterialShaderProgramCreator::parseShaderProgramTag(
-	const boost::property_tree::ptree& pt)
-{
-	usingTexCoordsAttrib = usingNormalAttrib = usingTangentAttrib = false;
-
-	using namespace boost::property_tree;
-
-	srcLines.push_back(
-		"#pragma anki start vertexShader\n"
-		"#pragma anki include \"shaders/MaterialVertex.glsl\"\n"
-		"#pragma anki start fragmentShader\n"
-		"#pragma anki include \"shaders/MaterialFragmentVariables.glsl\"");
+	const std::string& type = pt.get<std::string>("type");
+	srcLines.push_back("#pragma anki start " + type + "Shader");
 
 	//
 	// <includes></includes>
 	//
-	boost::ptr_vector<FuncDefinition> funcDefs;
 	std::vector<std::string> includeLines;
 
 	const ptree& includesPt = pt.get_child("includes");
@@ -440,33 +61,31 @@ void MaterialShaderProgramCreator::parseShaderProgramTag(
 	{
 		if(v.first != "include")
 		{
-			throw ANKI_EXCEPTION("Expected include and not: " + v.first);
+			throw ANKI_EXCEPTION("Expected \"include\" tag 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);
+	//std::sort(includeLines.begin(), includeLines.end(), compareStrings);
 	srcLines.insert(srcLines.end(), includeLines.begin(), includeLines.end());
 
 	//
-	// <ins></ins>
+	// <inputs></inputs>
 	//
-
-	// Store the source of the uniform vars
-	std::vector<std::string> uniformsLines;
-
 	boost::optional<const ptree&> insPt = pt.get_child_optional("inputs");
 	if(insPt)
 	{
+		// Store the source of the uniform vars
+		std::vector<std::string> uniformsLines;
+	
 		BOOST_FOREACH(const ptree::value_type& v, insPt.get())
 		{
 			if(v.first != "input")
 			{
-				throw ANKI_EXCEPTION("Expected in and not: " + v.first);
+				throw ANKI_EXCEPTION("Expected \"input\" tag and not: " + 
+					v.first);
 			}
 
 			const ptree& inPt = v.second;
@@ -492,44 +111,18 @@ void MaterialShaderProgramCreator::parseShaderProgramTag(
 	{
 		if(v.first != "operation")
 		{
-			throw ANKI_EXCEPTION("Expected operation and not: " + v.first);
+			throw ANKI_EXCEPTION("Expected \"operation\" tag and not: " + 
+				v.first);
 		}
 
 		const ptree& opPt = v.second;
-		parseOperatorTag(opPt);
+		parseOperationTag(opPt);
 	} // end for all operations
 
 	srcLines.push_back("}\n");
-
-	//
-	// Create the output
-	//
-	if(usingTexCoordsAttrib)
-	{
-		srcLines.insert(srcLines.begin(), "#define USING_TEX_COORDS_ATTRIB");
-	}
-
-	if(usingNormalAttrib)
-	{
-		srcLines.insert(srcLines.begin(), "#define USING_NORMAL_ATTRIB");
-	}
-
-	if(usingTangentAttrib)
-	{
-		srcLines.insert(srcLines.begin(), "#define USING_TANGENT_ATTRIB");
-	}
-
-	BOOST_FOREACH(const std::string& line, srcLines)
-	{
-		source += line + "\n";
-	}
-
-	//std::cout << source << std::endl;
 }
 
 
-//==============================================================================
-// parseInputTag                                                               =
 //==============================================================================
 void MaterialShaderProgramCreator::parseInputTag(
 	const boost::property_tree::ptree& pt, std::string& line)
@@ -538,144 +131,70 @@ void MaterialShaderProgramCreator::parseInputTag(
 
 	const std::string& name = pt.get<std::string>("name");
 	const std::string& type = pt.get<std::string>("type");
-	boost::optional<const ptree&> valuePt = pt.get_child_optional("value");
-	GLenum glType;
-
-	// Buildin or varying
-	if(!valuePt)
-	{
-		MaterialBuildinVariable::MatchingVariable tmp;
-
-		if(MaterialBuildinVariable::isBuildin(name.c_str(), &tmp, &glType))
-		{
-			const char* glTypeTxt = glTypeToTxt.at(glType);
-			line += "uniform ";
-			line += glTypeTxt;
-		}
-		else if(varyingNameToGlType.find(name.c_str()) !=
-			varyingNameToGlType.end())
-		{
-			glType = varyingNameToGlType.at(name.c_str());
-			const char* glTypeTxt = glTypeToTxt.at(glType);
-
-			line += "in ";
-			line += glTypeTxt;
-
-			// Set a few flags
-			if(name == "vTexCoords")
-			{
-				usingTexCoordsAttrib = true;
-			}
-			else if(name == "vNormal")
-			{
-				usingNormalAttrib = true;
-			}
-			else if(name == "vTangent" || name == "vTangentW")
-			{
-				usingTangentAttrib = true;
-			}
-		}
-		else
-		{
-			throw ANKI_EXCEPTION("The variable is not build-in or varying: " +
-				name);
-		}
-	}
-	else
-	{
-		if(valuePt.get().size() != 1)
-		{
-			throw ANKI_EXCEPTION("Bad <value> for <input>: " + name);
-		}
 
-		const ptree::value_type& v = valuePt.get().front();
-
-		// Wrong tag
-		if(txtToGlType.find(v.first.c_str()) == txtToGlType.end())
-		{
-			throw ANKI_EXCEPTION("Wrong type \"" + v.first + "\" for in: " +
-				name);
-		}
-
-		const std::string& typeTxt = v.first;
-
-		line += "uniform " + typeTxt;
-		glType = txtToGlType.at(typeTxt.c_str());
-	}
-
-	line += " " + name + ";";
+	line = "uniform " + type " " + 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
-	const FuncDefinition* def = NULL;
-	try
-	{
-		def = funcNameToDef.at(funcName.c_str());
-	}
-	catch(std::exception& e)
-	{
-		throw ANKI_EXCEPTION("Function is not defined in any include file: " +
-			funcName);
-	}
-
-	// Check args size
-	if(argsPt.size() != def->argDefinitions.size())
-	{
-		throw ANKI_EXCEPTION("Incorrect number of arguments for: " + funcName);
-	}
-
-	// Write return value
-	if(def->returnDataType != GL_NONE)
+	// <id></id>
+	int id = pt.get<int>("id");
+	
+	// <returnType></returnType>
+	boost::optional<const string&> retTypeOpt = 
+		pt.get_optional<const string&>("returnType");
+		
+	if(retTypeOpt)
 	{
-		line << def->returnDataTypeTxt << " operationOut" << id << " = ";
+		line << retTypeOpt.get() << " operationOut" << id << " = ";
 	}
-
-	// Func name
-	line << funcName + "(";
-
-	// Write all arguments
-	size_t i = 0;
-	BOOST_FOREACH(const ptree::value_type& v, argsPt)
+	
+	// <function>functionName</function>
+	const std::string& funcName = pt.get<std::string>("function");
+	
+	line << funcName << "(";
+	
+	// <arguments></arguments>
+	boost::optional<const ptree&> argsPt = pt.get_child_optional("arguments");
+	
+	if(argsPt)
 	{
-		if(v.first != "argument")
+		// Write all arguments
+		ptree::const_iterator it = argsPt.get();
+		for(; it != argsPt.get().end(); ++it)
 		{
-			throw ANKI_EXCEPTION("Unexpected tag \"" + v.first +
-				"\" for operation: " + boost::lexical_cast<std::string>(id));
-
-		}
+			const ptree::value_type& v = *it;
+		
+			if(v.first != "argument")
+			{
+				throw ANKI_EXCEPTION("Operation " +
+					boost::lexical_cast<std::string>(id) + 
+					": Expected \"argument\" tag and not: " + v.first);
+			}
 
-		const std::string& argName = v.second.data();
-		line << argName;
+			const std::string& argName = v.second.data();
+			line << argName;
 
-		// Add a comma
-		++i;
-		if(i != argsPt.size())
-		{
-			line << ", ";
+			// Add a comma
+			if(it != argsPt.get().end() - 1)
+			{
+				line << ", ";
+			}
 		}
 	}
+	
 	line << ");";
-
 	srcLines.push_back("\t" + line.str());
 }
 
 
-//==============================================================================
-// compareStrings                                                              =
 //==============================================================================
 bool MaterialShaderProgramCreator::compareStrings(
 	const std::string& a, const std::string& b)

+ 4 - 103
anki/resource/MaterialShaderProgramCreator.h

@@ -1,12 +1,8 @@
 #ifndef ANKI_RESOURCE_MATERIAL_SHADER_PROGRAM_CREATOR_H
 #define ANKI_RESOURCE_MATERIAL_SHADER_PROGRAM_CREATOR_H
 
-#include "anki/util/ConstCharPtrHashMap.h"
-#include "anki/util/scanner/Forward.h"
-#include <GL/glew.h>
-#include <vector>
+#include "anki/util/StringList.h"
 #include <boost/property_tree/ptree_fwd.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
 
 
 namespace anki {
@@ -29,105 +25,11 @@ class MaterialShaderProgramCreator
 		}
 
 	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;
-
-		/// This holds the varyings that come from the vertex shader to the
-		/// fragment. These varyings can be used in the ins
-		/// - vTexCoords
-		/// - vNormal
-		/// - vTangent
-		/// - vTangentW
-		/// - vVertPosViewSpace
-		static ConstCharPtrHashMap<GLenum>::Type varyingNameToGlType;
-
-		/// @name Using attribute flag
-		/// Keep a few flags here to set a few defines in the shader program
-		/// source. The parseInputTag sets them
-		/// @{
-		bool usingTexCoordsAttrib;
-		bool usingNormalAttrib;
-		bool usingTangentAttrib;
-		/// @}
-
 		/// The lines of the shader program source
-		std::vector<std::string> srcLines;
+		StringList srcLines;
 
 		std::string source; ///< Shader program final source
 
-		//======================================================================
-		// Methods                                                             =
-		//======================================================================
-
-		/// Parses a glsl file for function definitions. It appends the
-		/// funcDefs container with new function definitions
-		/// @param[out] funcDefs Container that holds the function definitions
-		/// @param[out] funcNameToDef Go from function name to function
-		/// definition
-		void parseShaderFileForFunctionDefinitions(const char* filename,
-			boost::ptr_vector<FuncDefinition>& funcDefs,
-			ConstCharPtrHashMap<FuncDefinition*>::Type& funcNameToDef);
-
-		/// Used by parseShaderFileForFunctionDefinitions to skip preprocessor
-		/// definitions. Takes into account the backslashes. For example for
-		/// @code
-		/// #define ANKI_RESOURCE_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);
 
@@ -136,8 +38,7 @@ class MaterialShaderProgramCreator
 		void parseShaderProgramTag(const boost::property_tree::ptree& pt);
 
 		/// Parse what is within the
-		/// @code <*Shader></*Shader> @endcode where * may be fragment, vertex
-		/// etc
+		/// @code <shader></shader> @endcode
 		void parseShaderTag(const boost::property_tree::ptree& pt);
 
 		/// Parse what is within the @code <input></input> @endcode
@@ -145,7 +46,7 @@ class MaterialShaderProgramCreator
 			std::string& line);
 
 		/// Parse what is within the @code <operation></operation> @endcode
-		void parseOperatorTag(const boost::property_tree::ptree& pt);
+		void parseOperationTag(const boost::property_tree::ptree& pt);
 };
 
 

+ 21 - 11
anki/resource/MaterialVariable.h

@@ -25,21 +25,31 @@ class MaterialVariable
 			T_USER,
 			T_BUILDIN
 		};
+		
+		/// The data union
+		typedef boost::variant<float, Vec2, Vec3, Vec4, Mat3, 
+			Mat4, TextureResourcePointer> Variant;
 
-		/// XXX Used for initialization in the constructor
-		typedef boost::array<const ShaderProgram*, PASS_TYPES_NUM>
+		/// Used for initialization in the constructor
+		typedef std::vector<std::vector<ShaderProgram*> >
 			ShaderPrograms;
 
-		/// XXX
-		typedef boost::array<const ShaderProgramVariable*,
-			PASS_TYPES_NUM> ShaderProgramVariables;
-
-		/// Constructor
+		/// @name Constructors & destructor
+		/// @{
+		
+		/// Build-in
 		MaterialVariable(
-			Type type,
 			const char* shaderProgVarName,
-			const ShaderPrograms& shaderProgsArr);
-
+			const ShaderPrograms& sProgs);
+			
+		/// User defined
+		<template Type>
+		MaterialVariable(
+			const char* shaderProgVarName,
+			const ShaderPrograms& sProgs,
+			const Type& val);
+		/// @}
+			
 		/// @name Accessors
 		/// @{
 		Type getType() const
@@ -53,7 +63,7 @@ class MaterialVariable
 
 		/// Check if pass p needs this variable. Check if the shader program
 		/// of p contains this variable or not
-		bool inPass(PassType p) const
+		bool inPass(uint p) const
 		{
 			return sProgVars[p] != NULL;
 		}

+ 39 - 0
anki/util/StringList.h

@@ -0,0 +1,39 @@
+#ifndef ANKI_UTIL_STRING_LIST_H
+#define ANKI_UTIL_STRING_LIST_H
+
+#include <vector>
+#include <string>
+
+
+namespace anki {
+
+
+/// A simple convenience class
+class StringList: public std::vector<std::string>
+{
+	public:
+		typedef std::vector<std::string> Base; ///< Its the vector of strings
+		typedef Base::value_type ValueType; ///< Its string
+
+		void join(const ValueType& sep, ValueType& out) const;
+};
+
+
+inline void StringList::join(const ValueType& sep, ValueType& out) const
+{
+	Base::const_iterator it = begin();
+	for(; it != end(); it++)
+	{
+		out += *it;
+		if(it != end() - 1)
+		{
+			out += sep;
+		}
+	}
+}
+
+
+} // end namespace
+
+
+#endif