Prechádzať zdrojové kódy

Refactoring material towards tessellation

Panagiotis Christopoulos Charitos 12 rokov pred
rodič
commit
f2e08f6db1

+ 6 - 0
include/anki/gl/GlState.h

@@ -95,6 +95,8 @@ public:
 
 
 	void setDepthMaskEnabled(const Bool enable);
 	void setDepthMaskEnabled(const Bool enable);
 	void setDepthFunc(const GLenum val);
 	void setDepthFunc(const GLenum val);
+
+	void setPolygonMode(const GLenum mode);
 	/// @}
 	/// @}
 
 
 private:
 private:
@@ -109,6 +111,10 @@ private:
 	Array<GLint, 4> colorMask;
 	Array<GLint, 4> colorMask;
 	GLint depthMask;
 	GLint depthMask;
 	GLenum depthFunc;
 	GLenum depthFunc;
+
+#if ANKI_GL == ANKI_GL_DESKTOP
+	GLenum polyMode;
+#endif
 	/// @}
 	/// @}
 
 
 	/// Sync the local members with the opengl ones
 	/// Sync the local members with the opengl ones

+ 29 - 43
include/anki/resource/Material.h

@@ -1,12 +1,12 @@
 #ifndef ANKI_RESOURCE_MATERIAL_H
 #ifndef ANKI_RESOURCE_MATERIAL_H
 #define ANKI_RESOURCE_MATERIAL_H
 #define ANKI_RESOURCE_MATERIAL_H
 
 
-#include "anki/resource/MaterialCommon.h"
 #include "anki/resource/Resource.h"
 #include "anki/resource/Resource.h"
-#include "anki/util/Dictionary.h"
-#include "anki/util/StringList.h"
+#include "anki/resource/ShaderProgramResource.h"
+#include "anki/resource/PassLevelKey.h"
 #include "anki/Math.h"
 #include "anki/Math.h"
 #include "anki/util/Visitor.h"
 #include "anki/util/Visitor.h"
+#include "anki/util/Dictionary.h"
 #include "anki/util/NonCopyable.h"
 #include "anki/util/NonCopyable.h"
 #include "anki/gl/Ogl.h"
 #include "anki/gl/Ogl.h"
 #include <memory>
 #include <memory>
@@ -14,15 +14,8 @@
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
-class ShaderProgram;
-class ShaderProgramUniformVariable;
 class XmlElement;
 class XmlElement;
 class MaterialShaderProgramCreator;
 class MaterialShaderProgramCreator;
-class ShaderProgramUniformBlock;
-
-// A few consts
-const U32 MATERIAL_MAX_PASSES = 4;
-const U32 MATERIAL_MAX_LODS = 4;
 
 
 // Forward
 // Forward
 template<typename T>
 template<typename T>
@@ -49,16 +42,11 @@ class MaterialVariable: public MateriaVariableVisitable, public NonCopyable
 public:
 public:
 	typedef MateriaVariableVisitable Base;
 	typedef MateriaVariableVisitable Base;
 
 
-	/// Given a pair of pass and level it returns a pointer to a
-	/// shader program uniform variable. The pointer may be nullptr
-	typedef PassLevelHashMap<const ShaderProgramUniformVariable*>
-		PassLevelToShaderProgramUniformVariableHashMap;
-
 	/// @name Constructors & destructor
 	/// @name Constructors & destructor
 	/// @{
 	/// @{
 	MaterialVariable(
 	MaterialVariable(
 		const char* shaderProgVarName,
 		const char* shaderProgVarName,
-		PassLevelToShaderProgramHashMap& progs)
+		PassLodArray<ShaderProgramResourcePointer>& progs)
 	{
 	{
 		init(shaderProgVarName, progs);
 		init(shaderProgVarName, progs);
 	}
 	}
@@ -91,9 +79,7 @@ public:
 	const ShaderProgramUniformVariable* findShaderProgramUniformVariable(
 	const ShaderProgramUniformVariable* findShaderProgramUniformVariable(
 		const PassLevelKey& key) const
 		const PassLevelKey& key) const
 	{
 	{
-		PassLevelToShaderProgramUniformVariableHashMap::const_iterator it =
-			sProgVars.find(key);
-		return (it == sProgVars.end()) ? nullptr : it->second;
+		return progVars[key.pass][key.level];
 	}
 	}
 
 
 	/// Get the GL data type of all the shader program variables
 	/// Get the GL data type of all the shader program variables
@@ -113,7 +99,7 @@ public:
 	/// @}
 	/// @}
 
 
 private:
 private:
-	PassLevelToShaderProgramUniformVariableHashMap sProgVars;
+	PassLodArray<const ShaderProgramUniformVariable*> progVars;
 
 
 	/// Keep one ShaderProgramVariable here for easy access of the common
 	/// Keep one ShaderProgramVariable here for easy access of the common
 	/// variable stuff like name or GL data type etc
 	/// variable stuff like name or GL data type etc
@@ -121,7 +107,7 @@ private:
 
 
 	/// Common constructor code
 	/// Common constructor code
 	void init(const char* shaderProgVarName,
 	void init(const char* shaderProgVarName,
-		PassLevelToShaderProgramHashMap& shaderProgsArr);
+		PassLodArray<ShaderProgramResourcePointer>& progs);
 };
 };
 
 
 /// Material variable with data. A complete type
 /// Material variable with data. A complete type
@@ -135,7 +121,7 @@ public:
 	/// @{
 	/// @{
 	MaterialVariableTemplate(
 	MaterialVariableTemplate(
 		const char* shaderProgVarName,
 		const char* shaderProgVarName,
-		PassLevelToShaderProgramHashMap& progs)
+		PassLodArray<ShaderProgramResourcePointer>& progs)
 		: MaterialVariable(shaderProgVarName, progs)
 		: MaterialVariable(shaderProgVarName, progs)
 	{
 	{
 		setupVisitable(this);
 		setupVisitable(this);
@@ -177,14 +163,14 @@ class MaterialProperties
 public:
 public:
 	/// @name Accessors
 	/// @name Accessors
 	/// @{
 	/// @{
-	const StringList& getPasses() const
+	U getLevelsOfDetail() const
 	{
 	{
-		return passes;
+		return lodsCount;
 	}
 	}
 
 
-	U32 getLevelsOfDetail() const
+	U getPassesCount() const
 	{
 	{
-		return levelsOfDetail;
+		return passesCount;
 	}
 	}
 
 
 	Bool getShadow() const
 	Bool getShadow() const
@@ -220,16 +206,15 @@ public:
 	}
 	}
 
 
 protected:
 protected:
-	StringList passes;
-
-	U32 levelsOfDetail = 1;
-
 	GLenum blendingSfactor = GL_ONE; ///< Default GL_ONE
 	GLenum blendingSfactor = GL_ONE; ///< Default GL_ONE
 	GLenum blendingDfactor = GL_ZERO; ///< Default GL_ZERO
 	GLenum blendingDfactor = GL_ZERO; ///< Default GL_ZERO
 
 
 	Bool8 depthTesting = true;
 	Bool8 depthTesting = true;
 	Bool8 wireframe = false;
 	Bool8 wireframe = false;
 	Bool8 shadow = true;
 	Bool8 shadow = true;
+
+	U8 passesCount = 1;
+	U8 lodsCount = 1;
 };
 };
 
 
 /// Material resource
 /// Material resource
@@ -310,9 +295,6 @@ class Material: public MaterialProperties, public NonCopyable
 public:
 public:
 	typedef PtrVector<MaterialVariable> VarsContainer;
 	typedef PtrVector<MaterialVariable> VarsContainer;
 
 
-	/// Type for garbage collection
-	typedef PtrVector<ShaderProgramResourcePointer> ShaderPrograms;
-
 	Material();
 	Material();
 	~Material();
 	~Material();
 
 
@@ -335,17 +317,24 @@ public:
 	{
 	{
 		return commonUniformBlock;
 		return commonUniformBlock;
 	}
 	}
+	/// @}
 
 
-	const ShaderPrograms& getShaderPrograms() const
+	const ShaderProgram& findShaderProgram(const PassLevelKey& key) const
 	{
 	{
-		return progs;
+		ANKI_ASSERT(progs[key.pass][key.level].isLoaded());
+		return *progs[key.pass][key.level];
 	}
 	}
-	/// @}
 
 
-	const ShaderProgram& findShaderProgram(const PassLevelKey& key) const
+	const ShaderProgram* tryFindShaderProgram(const PassLevelKey& key) const
 	{
 	{
-		ANKI_ASSERT(eSProgs.find(key) != eSProgs.end());
-		return *eSProgs.at(key);
+		if(progs[key.pass][key.level].isLoaded())
+		{
+			return progs[key.pass][key.level].get();
+		}
+		else
+		{
+			return nullptr;
+		}
 	}
 	}
 
 
 	/// Get by name
 	/// Get by name
@@ -377,10 +366,7 @@ private:
 	/// The most important aspect of materials. These are all the shader
 	/// The most important aspect of materials. These are all the shader
 	/// programs per level and per pass. Their number are NP * NL where
 	/// 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
 	/// NP is the number of passes and NL the number of levels of detail
-	ShaderPrograms progs;
-
-	/// For searching
-	PassLevelToShaderProgramHashMap eSProgs;
+	PassLodArray<ShaderProgramResourcePointer> progs;
 
 
 	/// Used for sorting
 	/// Used for sorting
 	std::size_t hash;
 	std::size_t hash;

+ 0 - 14
include/anki/resource/MaterialCommon.h

@@ -1,14 +0,0 @@
-#ifndef ANKI_RESOURCE_MATERIAL_COMMON_H
-#define ANKI_RESOURCE_MATERIAL_COMMON_H
-
-#include "anki/resource/PassLevelKey.h"
-
-namespace anki {
-
-/// Given a pair of pass and level it returns a pointer to a shader program
-typedef PassLevelHashMap<class ShaderProgram*>
-	PassLevelToShaderProgramHashMap;
-
-} // end namespace anki
-
-#endif

+ 0 - 3
include/anki/resource/Model.h

@@ -104,9 +104,6 @@ template<typename MeshResourcePointerType>
 class ModelPatch: public ModelPatchBase
 class ModelPatch: public ModelPatchBase
 {
 {
 public:
 public:
-	/// Map to get the VAO given a PassLod key
-	typedef PassLevelHashMap<Vao> PassLevelToVaoMap;
-
 	ModelPatch(const char* meshFNames[], U32 meshesCount,
 	ModelPatch(const char* meshFNames[], U32 meshesCount,
 		const char* mtlFName)
 		const char* mtlFName)
 	{
 	{

+ 14 - 30
include/anki/resource/PassLevelKey.h

@@ -2,8 +2,8 @@
 #define ANKI_RESOURCE_PASS_LEVEL_KEY_H
 #define ANKI_RESOURCE_PASS_LEVEL_KEY_H
 
 
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
-#include <unordered_map>
-#include <cstdlib>
+#include "anki/util/Assert.h"
+#include "anki/util/Array.h"
 
 
 namespace anki {
 namespace anki {
 
 
@@ -13,13 +13,12 @@ enum Pass
 	COLOR_PASS, ///< For MS
 	COLOR_PASS, ///< For MS
 	DEPTH_PASS, ///< For shadows
 	DEPTH_PASS, ///< For shadows
 
 
-	/// For MS color pass after early Z. It's different than COLOR because it
-	/// doesn't do any discard, earlyZ did it before
-	//COLOR_EARLYZ_PASS,
-
 	PASS_COUNT
 	PASS_COUNT
 };
 };
 
 
+/// Max level of detail
+const U MAX_LOD = 3;
+
 /// A key that consistst of the rendering pass and the level of detail
 /// A key that consistst of the rendering pass and the level of detail
 struct PassLevelKey
 struct PassLevelKey
 {
 {
@@ -28,41 +27,26 @@ struct PassLevelKey
 
 
 	PassLevelKey()
 	PassLevelKey()
 		: pass(COLOR_PASS), level(0)
 		: pass(COLOR_PASS), level(0)
-	{}
+	{
+		ANKI_ASSERT(level <= MAX_LOD);
+	}
 
 
 	PassLevelKey(const PassLevelKey& b)
 	PassLevelKey(const PassLevelKey& b)
 		: pass(b.pass), level(b.level)
 		: pass(b.pass), level(b.level)
-	{}
-
-	explicit PassLevelKey(const U8 pass_, const U8 level_)
-		: pass(pass_), level(level_)
-	{}
-};
-
-/// Create hash functor
-struct PassLevelKeyCreateHash
-{
-	size_t operator()(const PassLevelKey& b) const
 	{
 	{
-		return ((U32)b.pass << 16) | (U32)b.level;
+		ANKI_ASSERT(level <= MAX_LOD);
 	}
 	}
-};
 
 
-/// Values comparisons functor
-struct PassLevelKeyComparision
-{
-	Bool operator()(const PassLevelKey& a,
-		const PassLevelKey& b) const
+	explicit PassLevelKey(const U8 pass_, const U8 level_)
+		: pass(pass_), level(level_)
 	{
 	{
-		return a.pass == b.pass && a.level == b.level;
+		ANKI_ASSERT(level <= MAX_LOD);
 	}
 	}
 };
 };
 
 
-/// Define an unorderer map with key the PassLevelKey and type given by a
-/// template parameter
+/// An array to store based on pass and LOD
 template<typename T>
 template<typename T>
-using PassLevelHashMap = std::unordered_map<
-	PassLevelKey, T, PassLevelKeyCreateHash, PassLevelKeyComparision>;
+using PassLodArray = Array2d<T, PASS_COUNT, MAX_LOD + 1>;
 
 
 } // end namespace anki
 } // end namespace anki
 
 

+ 8 - 8
shaders/MsCommonFrag.glsl

@@ -16,7 +16,7 @@ in highp vec2 vTexCoords;
 #define vInstanceId_DEFINED
 #define vInstanceId_DEFINED
 flat in mediump uint vInstanceId;
 flat in mediump uint vInstanceId;
 
 
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 in vec3 vNormal;
 in vec3 vNormal;
 #	define vNormal_DEFINED
 #	define vNormal_DEFINED
 in vec4 vTangent;
 in vec4 vTangent;
@@ -28,7 +28,7 @@ in vec3 vVertPosViewSpace;
 
 
 /// @name Fragment out
 /// @name Fragment out
 /// @{
 /// @{
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 #	if USE_MRT
 #	if USE_MRT
 layout(location = 0) out vec4 fMsFai0;
 layout(location = 0) out vec4 fMsFai0;
 layout(location = 1) out vec4 fMsFai1;
 layout(location = 1) out vec4 fMsFai1;
@@ -48,7 +48,7 @@ layout(location = 0) out uvec2 fMsFai0;
 /// @param[in] tangent Extra stuff for the tangent
 /// @param[in] tangent Extra stuff for the tangent
 /// @param[in] map The map
 /// @param[in] map The map
 /// @param[in] texCoords Texture coordinates
 /// @param[in] texCoords Texture coordinates
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 #	define getNormalFromTexture_DEFINED
 #	define getNormalFromTexture_DEFINED
 vec3 getNormalFromTexture(in vec3 normal, in vec4 tangent,
 vec3 getNormalFromTexture(in vec3 normal, in vec4 tangent,
 	in sampler2D map, in highp vec2 texCoords)
 	in sampler2D map, in highp vec2 texCoords)
@@ -71,7 +71,7 @@ vec3 getNormalFromTexture(in vec3 normal, in vec4 tangent,
 #endif
 #endif
 
 
 /// Just normalize
 /// Just normalize
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 #	define getNormalSimple_DEFINED
 #	define getNormalSimple_DEFINED
 vec3 getNormalSimple(in vec3 normal)
 vec3 getNormalSimple(in vec3 normal)
 {
 {
@@ -84,7 +84,7 @@ vec3 getNormalSimple(in vec3 normal)
 /// @param[in] normal Fragment's normal in view space as well
 /// @param[in] normal Fragment's normal in view space as well
 /// @param[in] map The env map
 /// @param[in] map The env map
 /// @return The color
 /// @return The color
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 #	define getEnvironmentColor_DEFINED
 #	define getEnvironmentColor_DEFINED
 vec3 getEnvironmentColor(in vec3 vertPosViewSpace, in vec3 normal,
 vec3 getEnvironmentColor(in vec3 vertPosViewSpace, in vec3 normal,
 	in sampler2D map)
 	in sampler2D map)
@@ -115,7 +115,7 @@ vec3 readTextureRgbAlphaTesting(
 	in highp vec2 texCoords,
 	in highp vec2 texCoords,
 	in float tolerance)
 	in float tolerance)
 {
 {
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 	vec4 col = vec4(texture(map, texCoords));
 	vec4 col = vec4(texture(map, texCoords));
 	if(col.a < tolerance)
 	if(col.a < tolerance)
 	{
 	{
@@ -137,7 +137,7 @@ vec3 readTextureRgbAlphaTesting(
 }
 }
 
 
 /// Just read the RGB color from texture
 /// Just read the RGB color from texture
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 #	define readRgbFromTexture_DEFINED
 #	define readRgbFromTexture_DEFINED
 vec3 readRgbFromTexture(in sampler2D tex, in highp vec2 texCoords)
 vec3 readRgbFromTexture(in sampler2D tex, in highp vec2 texCoords)
 {
 {
@@ -146,7 +146,7 @@ vec3 readRgbFromTexture(in sampler2D tex, in highp vec2 texCoords)
 #endif
 #endif
 
 
 /// Write the data to FAIs
 /// Write the data to FAIs
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 #	define writeFais_DEFINED
 #	define writeFais_DEFINED
 void writeFais(
 void writeFais(
 	in vec3 diffColor, // from 0 to 1
 	in vec3 diffColor, // from 0 to 1

+ 11 - 13
shaders/MsCommonVert.glsl

@@ -5,7 +5,7 @@
 /// @{
 /// @{
 layout(location = 0) in highp vec3 position;
 layout(location = 0) in highp vec3 position;
 layout(location = 3) in highp vec2 texCoord;
 layout(location = 3) in highp vec2 texCoord;
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 layout(location = 1) in mediump vec3 normal;
 layout(location = 1) in mediump vec3 normal;
 layout(location = 2) in mediump vec4 tangent;
 layout(location = 2) in mediump vec4 tangent;
 #endif
 #endif
@@ -19,7 +19,7 @@ out highp vec2 vTexCoords;
 flat out uint vInstanceId;
 flat out uint vInstanceId;
 #endif
 #endif
 
 
-#ifdef PASS_COLOR
+#if PASS_COLOR
 out mediump vec3 vNormal;
 out mediump vec3 vNormal;
 out mediump vec4 vTangent;
 out mediump vec4 vTangent;
 out mediump vec3 vVertPosViewSpace; ///< For env mapping. AKA view vector
 out mediump vec3 vVertPosViewSpace; ///< For env mapping. AKA view vector
@@ -27,35 +27,33 @@ out mediump vec3 vVertPosViewSpace; ///< For env mapping. AKA view vector
 /// @}
 /// @}
 
 
 //==============================================================================
 //==============================================================================
-#define setVaryings1_DEFINED
-void setVaryings1(in mat4 modelViewProjectionMat)
+#define writePositionTexCoord_DEFINED
+void writePositionTexCoord(in mat4 mvp)
 {
 {
-#if defined(PASS_DEPTH) && LOD > 0
+#if PASS_DEPTH && LOD > 0
 	// No tex coords for you
 	// No tex coords for you
 #else
 #else
 	vTexCoords = texCoord;
 	vTexCoords = texCoord;
 #endif
 #endif
 
 
-	gl_Position = modelViewProjectionMat * vec4(position, 1.0);
+	gl_Position = mvp * vec4(position, 1.0);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-#define setVaryings2_DEFINED
-void setVaryings2(
-	in mat4 modelViewProjectionMat, 
-	in mat3 normalMat)
+#define writePositionNormalTangentTexCoord_DEFINED
+void writePositionNormalTangentTexCoord(in mat4 mvp, in mat3 normalMat)
 {
 {
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 	vNormal = vec3(normalMat * normal);
 	vNormal = vec3(normalMat * normal);
 	vTangent.xyz = vec3(normalMat * tangent.xyz);
 	vTangent.xyz = vec3(normalMat * tangent.xyz);
 	vTangent.w = tangent.w;
 	vTangent.w = tangent.w;
 #endif
 #endif
 
 
-	setVaryings1(modelViewProjectionMat);
+	writePositionTexCoord(mvp);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-#if defined(PASS_COLOR)
+#if PASS_COLOR
 #define setVertPosViewSpace_DEFINED
 #define setVertPosViewSpace_DEFINED
 void setVertPosViewSpace(in mat4 modelViewMat)
 void setVertPosViewSpace(in mat4 modelViewMat)
 {
 {

+ 24 - 0
src/gl/GlState.cpp

@@ -221,6 +221,11 @@ void GlState::sync()
 	glGetIntegerv(GL_DEPTH_WRITEMASK, &depthMask);
 	glGetIntegerv(GL_DEPTH_WRITEMASK, &depthMask);
 	// depth func
 	// depth func
 	glGetIntegerv(GL_DEPTH_FUNC, (GLint*)&depthFunc);
 	glGetIntegerv(GL_DEPTH_FUNC, (GLint*)&depthFunc);
+
+	// Polygon mode
+#if ANKI_GL == ANKI_GL_DESKTOP
+	glGetIntegerv(GL_POLYGON_MODE, (GLint*)&polyMode);
+#endif
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -328,4 +333,23 @@ void GlState::setDepthFunc(const GLenum val)
 	}
 	}
 }
 }
 
 
+//==============================================================================
+void GlState::setPolygonMode(const GLenum mode)
+{
+#if ANKI_GL == ANKI_GL_DESKTOP
+
+#if ANKI_DEBUG
+	GLint real;
+	glGetIntegerv(GL_POLYGON_MODE, &real);
+	ANKI_ASSERT((GLenum)real == polyMode);
+#endif
+
+	if(mode != polyMode)
+	{
+		glPolygonMode(GL_FRONT_AND_BACK, mode);
+		polyMode = mode;
+	}
+#endif
+}
+
 } // end namespace anki
 } // end namespace anki

+ 8 - 4
src/renderer/Drawer.cpp

@@ -294,7 +294,7 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 	RenderComponent* renderable = rsn.getRenderComponent();
 	RenderComponent* renderable = rsn.getRenderComponent();
 	ANKI_ASSERT(renderable);
 	ANKI_ASSERT(renderable);
 
 
-	/* Instancing */
+	// Instancing
 	U32 instancesCount = renderable->getRenderInstancesCount();
 	U32 instancesCount = renderable->getRenderInstancesCount();
 
 
 	if(ANKI_UNLIKELY(instancesCount < 1))
 	if(ANKI_UNLIKELY(instancesCount < 1))
@@ -302,7 +302,9 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 		return;
 		return;
 	}
 	}
 
 
-	/* Blending */
+	GlState& gl = GlStateSingleton::get();
+
+	// Blending
 	const Material& mtl = renderable->getMaterial();
 	const Material& mtl = renderable->getMaterial();
 
 
 	Bool blending = mtl.isBlendingEnabled();
 	Bool blending = mtl.isBlendingEnabled();
@@ -321,11 +323,13 @@ void RenderableDrawer::render(SceneNode& frsn, RenderingStage stage,
 			return;
 			return;
 		}
 		}
 
 
-		GlStateSingleton::get().setBlendFunctions(
+		gl.setBlendFunctions(
 			mtl.getBlendingSfactor(), mtl.getBlendingDfactor());
 			mtl.getBlendingSfactor(), mtl.getBlendingDfactor());
 	}
 	}
 
 
-	GlStateSingleton::get().enable(GL_BLEND, blending);
+	gl.enable(GL_BLEND, blending);
+
+	gl.setPolygonMode(mtl.getWireframe() ? GL_LINE : GL_FILL);
 
 
 	// Calculate the LOD
 	// Calculate the LOD
 	Vec3 camPos = fr.getFrustumOrigin();
 	Vec3 camPos = fr.getFrustumOrigin();

+ 62 - 52
src/resource/Material.cpp

@@ -83,6 +83,23 @@ static GLenum blendToEnum(const char* str)
 #undef TXT_AND_ENUM
 #undef TXT_AND_ENUM
 }
 }
 
 
+//==============================================================================
+/// Iterate loaded programs
+template<typename Func>
+void iterateProgs(PassLodArray<ShaderProgramResourcePointer>& progs, Func func)
+{
+	for(U i = 0; i < PASS_COUNT; i++)
+	{
+		for(U j = 0; j < MAX_LOD + 1; j++)
+		{
+			if(progs[i][j].isLoaded())
+			{
+				func(progs[i][j], (Pass)i, j);
+			}
+		}
+	}
+}
+
 //==============================================================================
 //==============================================================================
 // MaterialVariable                                                            =
 // MaterialVariable                                                            =
 //==============================================================================
 //==============================================================================
@@ -105,23 +122,21 @@ const std::string& MaterialVariable::getName() const
 
 
 //==============================================================================
 //==============================================================================
 void MaterialVariable::init(const char* shaderProgVarName,
 void MaterialVariable::init(const char* shaderProgVarName,
-	PassLevelToShaderProgramHashMap& progs)
+	PassLodArray<ShaderProgramResourcePointer>& progs)
 {
 {
 	oneSProgVar = NULL;
 	oneSProgVar = NULL;
+	memset(&progVars, 0, sizeof(progVars));
 
 
 	// For all programs
 	// For all programs
-	PassLevelToShaderProgramHashMap::iterator it = progs.begin();
-	for(; it != progs.end(); ++it)
+	iterateProgs(progs, [&](ShaderProgramResourcePointer& prog, Pass p, U lod)
 	{
 	{
-		const ShaderProgram& sProg = *(it->second);
-		const PassLevelKey& key = it->first;
-
 		// Variable exists put it the map
 		// Variable exists put it the map
 		const ShaderProgramUniformVariable* uni = 
 		const ShaderProgramUniformVariable* uni = 
-			sProg.tryFindUniformVariable(shaderProgVarName);
+			prog->tryFindUniformVariable(shaderProgVarName);
+
 		if(uni)
 		if(uni)
 		{
 		{
-			sProgVars[key] = uni;
+			progVars[p][lod] = uni;
 
 
 			// Set oneSProgVar
 			// Set oneSProgVar
 			if(!oneSProgVar)
 			if(!oneSProgVar)
@@ -138,7 +153,7 @@ void MaterialVariable::init(const char* shaderProgVarName,
 					+ shaderProgVarName);
 					+ shaderProgVarName);
 			}
 			}
 		}
 		}
-	}
+	});
 
 
 	// Extra sanity checks
 	// Extra sanity checks
 	if(!oneSProgVar)
 	if(!oneSProgVar)
@@ -186,32 +201,18 @@ void Material::load(const char* filename)
 //==============================================================================
 //==============================================================================
 void Material::parseMaterialTag(const XmlElement& materialEl)
 void Material::parseMaterialTag(const XmlElement& materialEl)
 {
 {
-	// passes
-	//
-	XmlElement passEl = materialEl.getChildElementOptional("passes");
-
-	if(passEl)
-	{
-		passes = StringList::splitString(passEl.getText(), ' ');
-	}
-	else
-	{
-		ANKI_LOGW("<passes> is not defined. Expect errors later");
-		passes.push_back("DUMMY");
-	}
-
 	// levelsOfDetail
 	// levelsOfDetail
 	//
 	//
 	XmlElement lodEl = materialEl.getChildElementOptional("levelsOfDetail");
 	XmlElement lodEl = materialEl.getChildElementOptional("levelsOfDetail");
 
 
 	if(lodEl)
 	if(lodEl)
 	{
 	{
-		int tmp = lodEl.getInt();
-		levelsOfDetail = (tmp < 1) ? 1 : tmp;
+		I tmp = lodEl.getInt();
+		lodsCount = (tmp < 1) ? 1 : tmp;
 	}
 	}
 	else
 	else
 	{
 	{
-		levelsOfDetail = 1;
+		lodsCount = 1;
 	}
 	}
 
 
 	// shadow
 	// shadow
@@ -241,6 +242,10 @@ void Material::parseMaterialTag(const XmlElement& materialEl)
 
 
 		disableDepthPass = true;
 		disableDepthPass = true;
 	}
 	}
+	else
+	{
+		passesCount = 2;
+	}
 
 
 	// depthTesting
 	// depthTesting
 	//
 	//
@@ -267,9 +272,9 @@ void Material::parseMaterialTag(const XmlElement& materialEl)
 	MaterialShaderProgramCreator mspc(
 	MaterialShaderProgramCreator mspc(
 		shaderProgramEl, ANKI_RENDERER_USE_MATERIAL_UBOS);
 		shaderProgramEl, ANKI_RENDERER_USE_MATERIAL_UBOS);
 
 
-	for(U32 level = 0; level < levelsOfDetail; ++level)
+	for(U level = 0; level < lodsCount; ++level)
 	{
 	{
-		for(U32 pid = 0; pid < PASS_COUNT; ++pid)
+		for(U pid = 0; pid < PASS_COUNT; ++pid)
 		{
 		{
 			if(disableDepthPass && pid == DEPTH_PASS)
 			if(disableDepthPass && pid == DEPTH_PASS)
 			{
 			{
@@ -278,25 +283,30 @@ void Material::parseMaterialTag(const XmlElement& materialEl)
 
 
 			std::stringstream src;
 			std::stringstream src;
 
 
-			src << "#define LOD " << level << "\n"
-				<< "#define PASS_" << passNames[pid] << "\n"
-				<< MainRendererSingleton::get().getShaderPostProcessorString() 
+			src << "#define LOD " << level << "\n";
+
+			for(U i = 0; i < PASS_COUNT; i++)
+			{
+				src << "#define PASS_" << passNames[i];
+
+				if(pid == i)
+				{
+					src << " 1\n";
+				}
+				else
+				{
+					src << " 0\n";
+				}
+			}
+
+			src << MainRendererSingleton::get().getShaderPostProcessorString() 
 				<< "\n"
 				<< "\n"
 				<< mspc.getShaderProgramSource() << std::endl;
 				<< mspc.getShaderProgramSource() << std::endl;
 
 
 			std::string filename =
 			std::string filename =
 				createShaderProgSourceToCache(src.str().c_str());
 				createShaderProgSourceToCache(src.str().c_str());
 
 
-			ShaderProgramResourcePointer* pptr =
-				new ShaderProgramResourcePointer;
-
-			pptr->load(filename.c_str());
-
-			ShaderProgram* sprog = pptr->get();
-
-			progs.push_back(pptr);
-
-			eSProgs[PassLevelKey(pid, level)] = sprog;
+			progs[pid][level].load(filename.c_str());
 		}
 		}
 	}
 	}
 
 
@@ -337,16 +347,16 @@ void Material::populateVariables(const MaterialShaderProgramCreator& mspc)
 	const char* blockName = "commonBlock";
 	const char* blockName = "commonBlock";
 
 
 	// Get default block
 	// Get default block
-	commonUniformBlock = (*progs[0])->tryFindUniformBlock(blockName);
+	commonUniformBlock = progs[0][0]->tryFindUniformBlock(blockName);
 
 
 	// Get all names of all the uniforms. Dont duplicate
 	// Get all names of all the uniforms. Dont duplicate
 	//
 	//
 	std::map<std::string, GLenum> allVarNames;
 	std::map<std::string, GLenum> allVarNames;
 
 
-	for(const ShaderProgramResourcePointer* sProg : progs)
+	iterateProgs(progs, [&](ShaderProgramResourcePointer& prog, Pass, U)
 	{
 	{
 		for(const ShaderProgramUniformVariable& v :
 		for(const ShaderProgramUniformVariable& v :
-			(*sProg)->getUniformVariables())
+			prog->getUniformVariables())
 		{
 		{
 #if ANKI_RENDERER_USE_MATERIAL_UBOS
 #if ANKI_RENDERER_USE_MATERIAL_UBOS
 			const ShaderProgramUniformBlock* bl = v.getUniformBlock();
 			const ShaderProgramUniformBlock* bl = v.getUniformBlock();
@@ -362,7 +372,7 @@ void Material::populateVariables(const MaterialShaderProgramCreator& mspc)
 
 
 			allVarNames[v.getName()] = v.getGlDataType();
 			allVarNames[v.getName()] = v.getGlDataType();
 		}
 		}
-	}
+	});
 
 
 	// Now combine
 	// Now combine
 	//
 	//
@@ -397,31 +407,31 @@ void Material::populateVariables(const MaterialShaderProgramCreator& mspc)
 		// sampler2D
 		// sampler2D
 		case GL_SAMPLER_2D:
 		case GL_SAMPLER_2D:
 			v = new MaterialVariableTemplate<TextureResourcePointer>(
 			v = new MaterialVariableTemplate<TextureResourcePointer>(
-				n, eSProgs);
+				n, progs);
 			break;
 			break;
 		// F32
 		// F32
 		case GL_FLOAT:
 		case GL_FLOAT:
-			v = new MaterialVariableTemplate<F32>(n, eSProgs);
+			v = new MaterialVariableTemplate<F32>(n, progs);
 			break;
 			break;
 		// vec2
 		// vec2
 		case GL_FLOAT_VEC2:
 		case GL_FLOAT_VEC2:
-			v = new MaterialVariableTemplate<Vec2>(n, eSProgs);
+			v = new MaterialVariableTemplate<Vec2>(n, progs);
 			break;
 			break;
 		// vec3
 		// vec3
 		case GL_FLOAT_VEC3:
 		case GL_FLOAT_VEC3:
-			v = new MaterialVariableTemplate<Vec3>(n, eSProgs);
+			v = new MaterialVariableTemplate<Vec3>(n, progs);
 			break;
 			break;
 		// vec4
 		// vec4
 		case GL_FLOAT_VEC4:
 		case GL_FLOAT_VEC4:
-			v = new MaterialVariableTemplate<Vec4>(n, eSProgs);
+			v = new MaterialVariableTemplate<Vec4>(n, progs);
 			break;
 			break;
 		// mat3
 		// mat3
 		case GL_FLOAT_MAT3:
 		case GL_FLOAT_MAT3:
-			v = new MaterialVariableTemplate<Mat3>(n, eSProgs);
+			v = new MaterialVariableTemplate<Mat3>(n, progs);
 			break;
 			break;
 		// mat4
 		// mat4
 		case GL_FLOAT_MAT4:
 		case GL_FLOAT_MAT4:
-			v = new MaterialVariableTemplate<Mat4>(n, eSProgs);
+			v = new MaterialVariableTemplate<Mat4>(n, progs);
 			break;
 			break;
 		// default is error
 		// default is error
 		default:
 		default:

+ 24 - 4
src/resource/MaterialShaderProgramCreator.cpp

@@ -17,7 +17,10 @@ namespace anki {
 enum
 enum
 {
 {
 	VERTEX = 1,
 	VERTEX = 1,
-	FRAGMENT = 2
+	TESSC,
+	TESSE,
+	GEOM,
+	FRAGMENT
 };
 };
 
 
 //==============================================================================
 //==============================================================================
@@ -197,6 +200,18 @@ void MaterialShaderProgramCreator::parseShaderTag(const XmlElement& shaderEl)
 	{
 	{
 		shader = VERTEX;
 		shader = VERTEX;
 	}
 	}
+	else if(type == "tessellationControl")
+	{
+		shader = TESSC;
+	}
+	else if(type == "tessellationEvaluation")
+	{
+		shader = TESSE;
+	}
+	else if(type == "geometry")
+	{
+		shader = GEOM;
+	}
 	else if(type == "fragment")
 	else if(type == "fragment")
 	{
 	{
 		shader = FRAGMENT;
 		shader = FRAGMENT;
@@ -296,7 +311,7 @@ void MaterialShaderProgramCreator::parseOperationTag(
 	std::string operationOut;
 	std::string operationOut;
 	if(retType != "void")
 	if(retType != "void")
 	{
 	{
-		operationOut = "operationOut" + std::to_string(id);
+		operationOut = "out" + std::to_string(id);
 	}
 	}
 	
 	
 	// <function>functionName</function>
 	// <function>functionName</function>
@@ -336,11 +351,16 @@ void MaterialShaderProgramCreator::parseOperationTag(
 					argsList.push_back(std::string(argEl.getText()) 
 					argsList.push_back(std::string(argEl.getText()) 
 						+ "[gl_InstanceID]");
 						+ "[gl_InstanceID]");
 				}
 				}
-				else
+				else if(shader == FRAGMENT)
 				{
 				{
 					argsList.push_back(std::string(argEl.getText()) 
 					argsList.push_back(std::string(argEl.getText()) 
 						+ "[vInstanceId]");
 						+ "[vInstanceId]");
 				}
 				}
+				else
+				{
+					throw ANKI_EXCEPTION(
+						"Cannot access the instance ID all shaders");
+				}
 			}
 			}
 			else
 			else
 			{
 			{
@@ -359,7 +379,7 @@ void MaterialShaderProgramCreator::parseOperationTag(
 	// Write the defines for the operationOuts
 	// Write the defines for the operationOuts
 	for(const std::string& arg : argsList)
 	for(const std::string& arg : argsList)
 	{
 	{
-		if(arg.find("operationOut") == 0)
+		if(arg.find("out") == 0)
 		{
 		{
 			lines << " && defined(" << arg << "_DEFINED)";
 			lines << " && defined(" << arg << "_DEFINED)";
 		}
 		}

+ 4 - 5
src/resource/Model.cpp

@@ -177,14 +177,13 @@ void ModelPatchBase::create()
 {
 {
 	U i = 0;
 	U i = 0;
 	const Material& mtl = getMaterial();
 	const Material& mtl = getMaterial();
-	U lodsCount = std::max(getMeshesCount(), mtl.getLevelsOfDetail());
-	U passesCount = mtl.getPasses().size();
+	U lodsCount = std::max<U>(getMeshesCount(), mtl.getLevelsOfDetail());
 
 
-	modelPatchProtected.vaos.resize(lodsCount * passesCount);
+	modelPatchProtected.vaos.resize(lodsCount * mtl.getPassesCount());
 
 
 	for(U lod = 0; lod < lodsCount; ++lod)
 	for(U lod = 0; lod < lodsCount; ++lod)
 	{
 	{
-		for(U pass = 0; pass < passesCount; ++pass)
+		for(U pass = 0; pass < mtl.getPassesCount(); ++pass)
 		{
 		{
 			PassLevelKey key(pass, lod);
 			PassLevelKey key(pass, lod);
 			const ShaderProgram* prog;
 			const ShaderProgram* prog;
@@ -201,7 +200,7 @@ void ModelPatchBase::create()
 			PassLevelKey shaderKey = key;
 			PassLevelKey shaderKey = key;
 			shaderKey.level = std::min(key.level,
 			shaderKey.level = std::min(key.level,
 				(U8)(getMaterial().getLevelsOfDetail() - 1));
 				(U8)(getMaterial().getLevelsOfDetail() - 1));
-			prog = &getMaterial().findShaderProgram(shaderKey);
+			prog = getMaterial().tryFindShaderProgram(shaderKey);
 
 
 			Vao vao;
 			Vao vao;
 			createVao(*prog, *mesh, vao);
 			createVao(*prog, *mesh, vao);

+ 1 - 1
testapp/Main.cpp

@@ -478,7 +478,7 @@ void mainLoop()
 
 
 		// Sleep
 		// Sleep
 		//
 		//
-#if 0
+#if 1
 		timer.stop();
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{
 		{

+ 3 - 7
tools/scene/diffNormTemplateMtl.h

@@ -1,10 +1,6 @@
 R"(<?xml version="1.0" encoding="UTF-8" ?>
 R"(<?xml version="1.0" encoding="UTF-8" ?>
 
 
 <material>
 <material>
-	<renderingStage>0</renderingStage>
-	
-	<passes>COLOR DEPTH</passes>
-
 	<shaderProgram>
 	<shaderProgram>
 		<inputs>
 		<inputs>
 			<input><type>mat4</type><name>modelViewProjectionMat</name><value></value><instanced>%instanced%</instanced></input>
 			<input><type>mat4</type><name>modelViewProjectionMat</name><value></value><instanced>%instanced%</instanced></input>
@@ -25,7 +21,7 @@ R"(<?xml version="1.0" encoding="UTF-8" ?>
 				<operation>
 				<operation>
 					<id>1</id>
 					<id>1</id>
 					<returnType>void</returnType>
 					<returnType>void</returnType>
-					<function>setVaryings2</function>
+					<function>writePositionNormalTangentTexCoord</function>
 					<arguments><argument>modelViewProjectionMat</argument><argument>normalMat</argument></arguments>
 					<arguments><argument>modelViewProjectionMat</argument><argument>normalMat</argument></arguments>
 				</operation>
 				</operation>
 			</operations>
 			</operations>
@@ -64,8 +60,8 @@ R"(<?xml version="1.0" encoding="UTF-8" ?>
 					<returnType>void</returnType>
 					<returnType>void</returnType>
 					<function>writeFais</function>
 					<function>writeFais</function>
 					<arguments>
 					<arguments>
-						<argument>operationOut0</argument>
-						<argument>operationOut1</argument>
+						<argument>out0</argument>
+						<argument>out1</argument>
 						<argument>specular</argument>
 						<argument>specular</argument>
 						<argument>0.0</argument>
 						<argument>0.0</argument>
 					</arguments>
 					</arguments>

+ 3 - 7
tools/scene/diffTemplateMtl.h

@@ -1,10 +1,6 @@
 R"(<?xml version="1.0" encoding="UTF-8" ?>
 R"(<?xml version="1.0" encoding="UTF-8" ?>
 
 
 <material>
 <material>
-	<renderingStage>0</renderingStage>
-	
-	<passes>COLOR DEPTH</passes>
-
 	<shaderProgram>
 	<shaderProgram>
 		<inputs>
 		<inputs>
 			<input><type>mat4</type><name>modelViewProjectionMat</name><value></value><instanced>%instanced%</instanced></input>
 			<input><type>mat4</type><name>modelViewProjectionMat</name><value></value><instanced>%instanced%</instanced></input>
@@ -24,7 +20,7 @@ R"(<?xml version="1.0" encoding="UTF-8" ?>
 				<operation>
 				<operation>
 					<id>1</id>
 					<id>1</id>
 					<returnType>void</returnType>
 					<returnType>void</returnType>
-					<function>setVaryings2</function>
+					<function>writePositionNormalTangentTexCoord</function>
 					<arguments><argument>modelViewProjectionMat</argument><argument>normalMat</argument></arguments>
 					<arguments><argument>modelViewProjectionMat</argument><argument>normalMat</argument></arguments>
 				</operation>
 				</operation>
 			</operations>
 			</operations>
@@ -60,8 +56,8 @@ R"(<?xml version="1.0" encoding="UTF-8" ?>
 					<returnType>void</returnType>
 					<returnType>void</returnType>
 					<function>writeFais</function>
 					<function>writeFais</function>
 					<arguments>
 					<arguments>
-						<argument>operationOut0</argument>
-						<argument>operationOut1</argument>
+						<argument>out0</argument>
+						<argument>out1</argument>
 						<argument>specular</argument>
 						<argument>specular</argument>
 						<argument>0.0</argument>
 						<argument>0.0</argument>
 					</arguments>
 					</arguments>