소스 검색

Reorganizing resources and gl
- Moving a few resources to gl
- Making a new resources
- Making texture creatio thread safe
- Misc changes in renderer (still under development)

Panagiotis Christopoulos Charitos 13 년 전
부모
커밋
a6549e55cf
65개의 변경된 파일1404개의 추가작업 그리고 1278개의 파일을 삭제
  1. 1 1
      anki/collision/Aabb.h
  2. 6 15
      anki/gl/BufferObject.cpp
  3. 10 8
      anki/gl/BufferObject.h
  4. 21 16
      anki/gl/Fbo.cpp
  5. 35 7
      anki/gl/Fbo.h
  6. 2 11
      anki/gl/GlException.cpp
  7. 0 108
      anki/gl/GlQuery.cpp
  8. 3 16
      anki/gl/GlStateMachine.cpp
  9. 4 1
      anki/gl/GlStateMachine.h
  10. 75 0
      anki/gl/Query.cpp
  11. 11 14
      anki/gl/Query.h
  12. 174 194
      anki/gl/ShaderProgram.cpp
  13. 102 70
      anki/gl/ShaderProgram.h
  14. 226 0
      anki/gl/Texture.cpp
  15. 216 0
      anki/gl/Texture.h
  16. 2 1
      anki/gl/TimeQuery.cpp
  17. 2 1
      anki/gl/TimeQuery.h
  18. 1 1
      anki/gl/Vao.cpp
  19. 19 16
      anki/gl/Vao.h
  20. 2 2
      anki/gl/Vbo.h
  21. 10 10
      anki/math/Axisang.inl.h
  22. 1 1
      anki/math/Euler.h
  23. 3 3
      anki/math/Mat3.h
  24. 3 3
      anki/math/Mat3.inl.h
  25. 4 4
      anki/math/Mat4.h
  26. 51 44
      anki/math/Mat4.inl.h
  27. 2 1
      anki/math/MathCommonIncludes.h
  28. 1 0
      anki/math/MathCommonSrc.h
  29. 1 1
      anki/math/Transform.h
  30. 3 3
      anki/math/Transform.inl.h
  31. 2 2
      anki/math/Vec2.h
  32. 2 2
      anki/math/Vec3.h
  33. 12 14
      anki/math/Vec3.inl.h
  34. 2 2
      anki/math/Vec4.h
  35. 6 11
      anki/math/Vec4.inl.h
  36. 30 35
      anki/renderer/Bl.cpp
  37. 7 4
      anki/renderer/Bl.h
  38. 3 5
      anki/renderer/Bs.cpp
  39. 16 13
      anki/renderer/Bs.h
  40. 2 2
      anki/renderer/Ez.h
  41. 1 1
      anki/renderer/Hdr.h
  42. 2 2
      anki/renderer/Is.h
  43. 1 1
      anki/renderer/Ms.h
  44. 1 1
      anki/renderer/Pps.h
  45. 2 2
      anki/renderer/Renderer.h
  46. 3 3
      anki/renderer/RenderingPass.h
  47. 4 4
      anki/renderer/Sm.h
  48. 1 1
      anki/renderer/Smo.h
  49. 4 4
      anki/renderer/Ssao.h
  50. 1 1
      anki/resource/LightRsrc.cpp
  51. 1 1
      anki/resource/LightRsrc.h
  52. 13 14
      anki/resource/Material.cpp
  53. 5 5
      anki/resource/Model.cpp
  54. 20 20
      anki/resource/Resource.h
  55. 80 0
      anki/resource/ShaderProgramResource.cpp
  56. 32 0
      anki/resource/ShaderProgramResource.h
  57. 2 1
      anki/resource/Skeleton.h
  58. 0 390
      anki/resource/Texture.cpp
  59. 0 153
      anki/resource/Texture.h
  60. 89 0
      anki/resource/TextureResource.cpp
  61. 32 0
      anki/resource/TextureResource.h
  62. 1 1
      anki/scene/Renderable.cpp
  63. 1 29
      anki/scene/Renderable.h
  64. 32 1
      anki/scene/Spatial.h
  65. 3 1
      anki/scene/VisibilityTester.cpp

+ 1 - 1
anki/collision/Aabb.h

@@ -87,7 +87,7 @@ public:
 		b = *this;
 	}
 
-	/// XXX Optimize it
+	/// It uses a nice trick to avoid unwanted calculations 
 	Aabb getTransformed(const Transform& transform) const;
 
 	/// Get a collision shape that includes this and the given. Its not

+ 6 - 15
anki/gl/BufferObject.cpp

@@ -7,32 +7,27 @@
 namespace anki {
 
 
-//==============================================================================
-// Destructor                                                                  =
 //==============================================================================
 BufferObject::~BufferObject()
 {
 	if(isCreated())
 	{
-		deleteBuff();
+		destroy();
 	}
 }
 
 
-//==============================================================================
-// create                                                                      =
 //==============================================================================
 void BufferObject::create(GLenum target_, uint sizeInBytes_,
 	const void* dataPtr, GLenum usage_)
 {
 	ANKI_ASSERT(!isCreated());
-	// unacceptable usage_
 
-	ANKI_ASSERT(usage_ == GL_STREAM_DRAW ||
-		usage_ == GL_STATIC_DRAW ||
-		usage_ == GL_DYNAMIC_DRAW);
+	ANKI_ASSERT(usage_ == GL_STREAM_DRAW
+		|| usage_ == GL_STATIC_DRAW
+		|| usage_ == GL_DYNAMIC_DRAW);
 
-	ANKI_ASSERT(sizeInBytes_ > 0); // unacceptable sizeInBytes
+	ANKI_ASSERT(sizeInBytes_ > 0 && "Unacceptable sizeInBytes");
 
 	usage = usage_;
 	target = target_;
@@ -47,7 +42,7 @@ void BufferObject::create(GLenum target_, uint sizeInBytes_,
 	glGetBufferParameteriv(target, GL_BUFFER_SIZE, &bufferSize);
 	if(sizeInBytes != (uint)bufferSize)
 	{
-		deleteBuff();
+		destroy();
 		throw ANKI_EXCEPTION("Data size mismatch");
 	}
 
@@ -56,8 +51,6 @@ void BufferObject::create(GLenum target_, uint sizeInBytes_,
 }
 
 
-//==============================================================================
-// write                                                                       =
 //==============================================================================
 void BufferObject::write(void* buff)
 {
@@ -71,8 +64,6 @@ void BufferObject::write(void* buff)
 }
 
 
-//==============================================================================
-// write                                                                       =
 //==============================================================================
 void BufferObject::write(void* buff, size_t offset, size_t size)
 {

+ 10 - 8
anki/gl/BufferObject.h

@@ -14,6 +14,8 @@ namespace anki {
 class BufferObject
 {
 public:
+	/// @name Constructors/Destructor
+	/// @{
 	BufferObject()
 		: glId(0)
 	{}
@@ -27,7 +29,8 @@ public:
 	}
 
 	/// It deletes the BO from the GL context
-	virtual ~BufferObject();
+	~BufferObject();
+	/// @}
 
 	/// @name Accessors
 	/// @{
@@ -73,18 +76,17 @@ public:
 	/// Creates a new BO with the given parameters and checks if everything
 	/// went OK. Throws exception if fails
 	/// @param target Depends on the BO
-	/// @param sizeInBytes The size of the buffer that we will allocate in
-	/// bytes
+	/// @param sizeInBytes The size of the buffer that we will allocate in bytes
 	/// @param dataPtr Points to the data buffer to copy to the VGA memory.
-	/// Put NULL if you want just to allocate memory
+	///		   Put NULL if you want just to allocate memory
 	/// @param usage It should be: GL_STREAM_DRAW or GL_STATIC_DRAW or
-	/// GL_DYNAMIC_DRAW only!!!!!!!!!
+	///		   GL_DYNAMIC_DRAW only!!!!!!!!!
 	/// @exception Exception
 	void create(GLenum target, uint sizeInBytes, const void* dataPtr,
 		GLenum usage);
 
 	/// Delete the BO
-	void deleteBuff()
+	void destroy()
 	{
 		ANKI_ASSERT(isCreated());
 		glDeleteBuffers(1, &glId);
@@ -111,7 +113,7 @@ public:
 	}
 
 private:
-	uint glId; ///< The OpenGL id of the BO
+	GLuint glId; ///< The OpenGL id of the BO
 
 	/// Used in glBindBuffer(target, glId) and its for easy access so we
 	/// wont have to query the GL driver. Its the type of the buffer eg
@@ -123,7 +125,7 @@ private:
 };
 
 
-} // end namespace
+} // end namespace anki
 
 
 #endif

+ 21 - 16
anki/gl/Fbo.cpp

@@ -1,12 +1,20 @@
 #include "anki/gl/Fbo.h"
+#include "anki/gl/Texture.h"
 #include <boost/lexical_cast.hpp>
+#include <array>
 
 
 namespace anki {
 
 
 //==============================================================================
-// Destructor                                                                  =
+
+static std::array<GLenum, 8> colorAttachments = {{
+	GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
+	GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5,
+	GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT7}};
+
+
 //==============================================================================
 Fbo::~Fbo()
 {
@@ -17,8 +25,6 @@ Fbo::~Fbo()
 }
 
 
-//==============================================================================
-// checkIfGood                                                                 =
 //==============================================================================
 void Fbo::checkIfGood() const
 {
@@ -29,14 +35,12 @@ void Fbo::checkIfGood() const
 
 	if(status != GL_FRAMEBUFFER_COMPLETE)
 	{
-		throw ANKI_EXCEPTION("FBO is incomplete: " +
-			boost::lexical_cast<std::string>(status));
+		throw ANKI_EXCEPTION("FBO is incomplete: " 
+			+ boost::lexical_cast<std::string>(status));
 	}
 }
 
 
-//==============================================================================
-// setNumOfColorAttachements                                                   =
 //==============================================================================
 void Fbo::setNumOfColorAttachements(uint num) const
 {
@@ -50,19 +54,12 @@ void Fbo::setNumOfColorAttachements(uint num) const
 	}
 	else
 	{
-		static GLenum colorAttachments[] = {
-			GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2,
-			GL_COLOR_ATTACHMENT3, GL_COLOR_ATTACHMENT4, GL_COLOR_ATTACHMENT5,
-			GL_COLOR_ATTACHMENT6, GL_COLOR_ATTACHMENT7};
-
-		ANKI_ASSERT(num <= sizeof(colorAttachments) / sizeof(GLenum));
-		glDrawBuffers(num, colorAttachments);
+		ANKI_ASSERT(num <= colorAttachments.size());
+		glDrawBuffers(num, &colorAttachments[0]);
 	}
 }
 
 
-//==============================================================================
-// getCurrentFbo                                                               =
 //==============================================================================
 uint Fbo::getCurrentFbo()
 {
@@ -72,4 +69,12 @@ uint Fbo::getCurrentFbo()
 }
 
 
+//==============================================================================
+void Fbo::setOtherAttachment(GLenum attachment, const Texture& tex)
+{
+	glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
+		GL_TEXTURE_2D, tex.getGlId(), 0);
+}
+
+
 } // end namespace

+ 35 - 7
anki/gl/Fbo.h

@@ -1,26 +1,31 @@
 #ifndef ANKI_GL_FBO_H
 #define ANKI_GL_FBO_H
 
-#include <GL/glew.h>
 #include "anki/util/Assert.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Exception.h"
+#include <GL/glew.h>
+#include <array>
 
 
 namespace anki {
 
 
+class Texture;
+
+
 /// The class is actually a wrapper to avoid common mistakes
 class Fbo
 {
 public:
-	/// Constructor
+	/// @name Constructors/Destructor
+	/// @{
 	Fbo()
 		: glId(0)
 	{}
 
-	/// Destructor
 	~Fbo();
+	/// @}
 
 	uint getGlId() const
 	{
@@ -33,9 +38,9 @@ public:
 	{
 		ANKI_ASSERT(isCreated());
 		target = target_;
-		ANKI_ASSERT(target == GL_DRAW_FRAMEBUFFER ||
-			target == GL_READ_FRAMEBUFFER ||
-			target == GL_FRAMEBUFFER);
+		ANKI_ASSERT(target == GL_DRAW_FRAMEBUFFER
+			|| target == GL_READ_FRAMEBUFFER
+			|| target == GL_FRAMEBUFFER);
 		glBindFramebuffer(target, glId);
 	}
 
@@ -52,6 +57,13 @@ public:
 	/// Set the number of color attachments of the FBO
 	void setNumOfColorAttachements(uint num) const;
 
+	/// Set the color attachments of this FBO
+	template<typename Container>
+	void setColorAttachments(const Container& textures);
+
+	/// Set other attachment
+	void setOtherAttachment(GLenum attachment, const Texture& tex);
+
 	/// Returns the GL id of the current attached FBO
 	/// @return Returns the GL id of the current attached FBO
 	static uint getCurrentFbo();
@@ -74,10 +86,26 @@ private:
 	uint glId; ///< OpenGL identification
 	GLenum target; ///< How the buffer is bind
 
-	bool isCreated() const {return glId != 0;}
+	bool isCreated() const
+	{
+		return glId != 0;
+	}
 };
 
 
+//==============================================================================
+template<typename Container>
+void Fbo::setColorAttachments(const Container& textures)
+{
+	setNumOfColorAttachements(textures.size());
+	for(size_t i = 0; i < textures.size(); ++i)
+	{
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
+			GL_TEXTURE_2D, textures[i]->getGlId(), 0);
+	}
+}
+
+
 } // end namespace
 
 

+ 2 - 11
anki/gl/GlException.cpp

@@ -1,8 +1,5 @@
 #include "anki/gl/GlException.h"
 #include "anki/util/Exception.h"
-#include "anki/util/Assert.h"
-#include "anki/core/Logger.h"
-#include "anki/core/Globals.h"
 #include <string>
 #include <GL/glew.h>
 
@@ -19,14 +16,8 @@ void glConditionalThrowException(const char* file, int line, const char* func)
 	}
 
 	const char* glerr = reinterpret_cast<const char*>(gluErrorString(errId));
-#if defined(NDEBUG)
-	throw Exception(std::string("OpenGL exception: ") + glerr, file, line,
-		func);
-#else
-	ANKI_ERROR("(" << file << ":" << line <<
-		" " << func << ") GL Error: " << glerr);
-	ANKI_ASSERT(0);
-#endif
+	std::string err = std::string("OpenGL exception: ") + glerr;
+	throw Exception(err.c_str(), file, line, func);
 }
 
 

+ 0 - 108
anki/gl/GlQuery.cpp

@@ -1,108 +0,0 @@
-#include "anki/gl/Query.h"
-#include "anki/util/Exception.h"
-#include "anki/util/Assert.h"
-#include <GL/glew.h>
-
-
-namespace anki {
-
-
-//==============================================================================
-// QueryImpl                                                                   =
-//==============================================================================
-
-/// Query implementation
-struct QueryImpl
-{
-	GLuint glId;
-	GLenum question;
-};
-
-
-//==============================================================================
-// Query                                                                       =
-//==============================================================================
-
-//==============================================================================
-Query::Query(QueryQuestion q)
-{
-	impl.reset(new QueryImpl);
-
-	// question
-	switch(q)
-	{
-		case QQ_SAMPLES_PASSED:
-			impl->question = GL_SAMPLES_PASSED;
-			break;
-		case QQ_ANY_SAMPLES_PASSED:
-			impl->question = GL_ANY_SAMPLES_PASSED;
-			break;
-		case QQ_TIME_ELAPSED:
-			impl->question = GL_TIME_ELAPSED;
-			break;
-		default:
-			ANKI_ASSERT(0);
-	};
-
-	// glId
-	glGenQueries(1, &impl->glId);
-	if(impl->glId == 0)
-	{
-		throw ANKI_EXCEPTION("Query generation failed");
-	}
-}
-
-
-//==============================================================================
-Query::~Query()
-{
-	glDeleteQueries(1, &impl->glId);
-}
-
-
-//==============================================================================
-void Query::beginQuery()
-{
-	glBeginQuery(impl->question, impl->glId);
-}
-
-
-//==============================================================================
-void Query::endQuery()
-{
-	glEndQuery(impl->question);
-}
-
-
-//==============================================================================
-uint64_t Query::getResult()
-{
-	GLuint64 result;
-	glGetQueryObjectui64v(impl->glId, GL_QUERY_RESULT, &result);
-	return result;
-}
-
-
-//==============================================================================
-uint64_t Query::getResultNoWait(bool& finished)
-{
-	GLuint resi;
-	glGetQueryObjectuiv(impl->glId, GL_QUERY_RESULT_AVAILABLE, &resi);
-
-	GLuint64 result;
-	if(resi)
-	{
-		glGetQueryObjectui64v(impl->glId, GL_QUERY_RESULT, &result);
-		finished = true;
-	}
-	else
-	{
-		finished = false;
-		result = 0;
-	}
-
-	return result;
-}
-
-
-} // end namespace anki

+ 3 - 16
anki/gl/GlStateMachine.cpp

@@ -8,8 +8,7 @@ namespace anki {
 // Statics                                                                     =
 //==============================================================================
 
-GLenum GlStateMachine::flagEnums[] =
-{
+GLenum GlStateMachine::flagEnums[] = {
 	GL_DEPTH_TEST,
 	GL_BLEND,
 	GL_STENCIL_TEST,
@@ -20,8 +19,6 @@ GLenum GlStateMachine::flagEnums[] =
 };
 
 
-//==============================================================================
-// enable                                                                      =
 //==============================================================================
 void GlStateMachine::enable(GLenum glFlag, bool enable)
 {
@@ -44,8 +41,6 @@ void GlStateMachine::enable(GLenum glFlag, bool enable)
 }
 
 
-//==============================================================================
-// isEnabled                                                                   =
 //==============================================================================
 bool GlStateMachine::isEnabled(GLenum glFlag)
 {
@@ -56,8 +51,6 @@ bool GlStateMachine::isEnabled(GLenum glFlag)
 }
 
 
-//==============================================================================
-// sync                                                                        =
 //==============================================================================
 void GlStateMachine::sync()
 {
@@ -81,13 +74,11 @@ void GlStateMachine::sync()
 }
 
 
-//==============================================================================
-// setViewport                                                                 =
 //==============================================================================
 void GlStateMachine::setViewport(uint x, uint y, uint w, uint h)
 {
-	if(x != (uint)viewportX || y != (uint)viewportY ||
-		w != (uint)viewportW || h != (uint)viewportH)
+	if(x != (uint)viewportX || y != (uint)viewportY 
+		|| w != (uint)viewportW || h != (uint)viewportH)
 	{
 		glViewport(x, y, w, h);
 		viewportX = x;
@@ -98,8 +89,6 @@ void GlStateMachine::setViewport(uint x, uint y, uint w, uint h)
 }
 
 
-//==============================================================================
-// useShaderProg                                                               =
 //==============================================================================
 void GlStateMachine::useShaderProg(GLuint id)
 {
@@ -113,8 +102,6 @@ void GlStateMachine::useShaderProg(GLuint id)
 }
 
 
-//==============================================================================
-// getCurrentProgramGlId                                                       =
 //==============================================================================
 GLuint GlStateMachine::getCurrentProgramGlId()
 {

+ 4 - 1
anki/gl/GlStateMachine.h

@@ -26,7 +26,10 @@ public:
 	/// only when needed
 	/// @{
 	void enable(GLenum flag, bool enable = true);
-	void disable(GLenum flag) {enable(flag, false);}
+	void disable(GLenum flag)
+	{
+		enable(flag, false);
+	}
 	bool isEnabled(GLenum flag);
 
 	void useShaderProg(GLuint id);

+ 75 - 0
anki/gl/Query.cpp

@@ -0,0 +1,75 @@
+#include "anki/gl/Query.h"
+#include "anki/util/Exception.h"
+#include "anki/util/Assert.h"
+
+
+namespace anki {
+
+
+//==============================================================================
+Query::Query(GLenum q)
+{
+	question = q;
+
+	// glId
+	glGenQueries(1, &glId);
+	if(glId == 0)
+	{
+		throw ANKI_EXCEPTION("Query generation failed");
+	}
+}
+
+
+//==============================================================================
+Query::~Query()
+{
+	glDeleteQueries(1, &glId);
+}
+
+
+//==============================================================================
+void Query::beginQuery()
+{
+	glBeginQuery(question, glId);
+}
+
+
+//==============================================================================
+void Query::endQuery()
+{
+	glEndQuery(question);
+}
+
+
+//==============================================================================
+uint64_t Query::getResult()
+{
+	GLuint64 result;
+	glGetQueryObjectui64v(glId, GL_QUERY_RESULT, &result);
+	return result;
+}
+
+
+//==============================================================================
+uint64_t Query::getResultNoWait(bool& finished)
+{
+	GLuint resi;
+	glGetQueryObjectuiv(glId, GL_QUERY_RESULT_AVAILABLE, &resi);
+
+	GLuint64 result;
+	if(resi)
+	{
+		glGetQueryObjectui64v(glId, GL_QUERY_RESULT, &result);
+		finished = true;
+	}
+	else
+	{
+		finished = false;
+		result = 0;
+	}
+
+	return result;
+}
+
+
+} // end namespace anki

+ 11 - 14
anki/gl/Query.h

@@ -1,8 +1,8 @@
 #ifndef ANKI_GL_QUERY_H
 #define ANKI_GL_QUERY_H
 
-#include <boost/scoped_ptr.hpp>
-#include <boost/integer.hpp>
+#include <cstdint>
+#include <GL/glew.h>
 
 
 namespace anki {
@@ -15,17 +15,13 @@ class QueryImpl;
 class Query
 {
 public:
-	enum QueryQuestion
-	{
-		QQ_SAMPLES_PASSED,
-		QQ_ANY_SAMPLES_PASSED, ///< Faster than the QQ_SAMPLES_PASSED
-		QQ_TIME_ELAPSED, ///< Time elapsed in ms
-		QQ_COUNT
-	};
-
 	/// @name Constructors/Destructor
 	/// @{
-	Query(QueryQuestion q);
+
+	/// @param q One of GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED, 
+	///        GL_TIME_ELAPSED
+	Query(GLenum q);
+
 	~Query();
 	/// @}
 
@@ -39,12 +35,13 @@ public:
 	/// @note Waits for operations to finish
 	uint64_t getResult();
 
-	/// Get results
-	/// @note Doesn't Wait for operations to finish
+	/// Get results. Doesn't Wait for operations to finish. If @a finished is 
+	/// false then the return value is irrelevant
 	uint64_t getResultNoWait(bool& finished);
 
 private:
-	boost::scoped_ptr<QueryImpl> impl;
+	GLuint glId;
+	GLenum question;
 };
 
 

+ 174 - 194
anki/resource/ShaderProgram.cpp → anki/gl/ShaderProgram.cpp

@@ -1,19 +1,9 @@
-#include "anki/resource/ShaderProgram.h"
-#include "anki/resource/ShaderProgramPrePreprocessor.h"
-#include "anki/core/App.h" // To get cache dir
+#include "anki/gl/ShaderProgram.h"
 #include "anki/gl/GlException.h"
 #include "anki/core/Logger.h"
 #include "anki/math/Math.h"
-#include "anki/util/Util.h"
-#include "anki/core/Globals.h"
 #include "anki/util/Exception.h"
-#include "anki/resource/Texture.h"
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/foreach.hpp>
-#include <boost/functional/hash.hpp>
-#include <fstream>
-#include <sstream>
+#include "anki/gl/Texture.h"
 
 
 namespace anki {
@@ -27,9 +17,9 @@ namespace anki {
 void ShaderProgramUniformVariable::doSanityChecks() const
 {
 	ANKI_ASSERT(getLocation() != -1);
-	ANKI_ASSERT(GlStateMachineSingleton::get().getCurrentProgramGlId() ==
-		getFatherSProg().getGlId());
-	ANKI_ASSERT(glGetUniformLocation(getFatherSProg().getGlId(),
+	ANKI_ASSERT(ShaderProgram::getCurrentProgram() == 
+		&getFatherShaderProgram());
+	ANKI_ASSERT(glGetUniformLocation(getFatherShaderProgram().getGlId(),
 		getName().c_str()) == getLocation());
 }
 
@@ -39,6 +29,7 @@ void ShaderProgramUniformVariable::set(const float x) const
 {
 	doSanityChecks();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT);
+	ANKI_ASSERT(getSize() == 1);
 
 	glUniform1f(getLocation(), x);
 }
@@ -47,6 +38,10 @@ void ShaderProgramUniformVariable::set(const float x) const
 //==============================================================================
 void ShaderProgramUniformVariable::set(const Vec2& x) const
 {
+	doSanityChecks();
+	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC2);
+	ANKI_ASSERT(getSize() == 2);
+
 	glUniform2f(getLocation(), x.x(), x.y());
 }
 
@@ -56,7 +51,8 @@ void ShaderProgramUniformVariable::set(const float x[], uint size) const
 {
 	doSanityChecks();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT);
-	ANKI_ASSERT(size > 1);
+	ANKI_ASSERT(getSize() == size);
+	
 	glUniform1fv(getLocation(), size, x);
 }
 
@@ -66,7 +62,8 @@ void ShaderProgramUniformVariable::set(const Vec2 x[], uint size) const
 {
 	doSanityChecks();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC2);
-	ANKI_ASSERT(size > 1);
+	ANKI_ASSERT(getSize() == size * 2);
+
 	glUniform2fv(getLocation(), size, &(const_cast<Vec2&>(x[0]))[0]);
 }
 
@@ -76,7 +73,8 @@ void ShaderProgramUniformVariable::set(const Vec3 x[], uint size) const
 {
 	doSanityChecks();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC3);
-	ANKI_ASSERT(size > 0);
+	ANKI_ASSERT(getSize() == size * 3);
+
 	glUniform3fv(getLocation(), size, &(const_cast<Vec3&>(x[0]))[0]);
 }
 
@@ -86,7 +84,8 @@ void ShaderProgramUniformVariable::set(const Vec4 x[], uint size) const
 {
 	doSanityChecks();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_VEC4);
-	ANKI_ASSERT(size > 0);
+	ANKI_ASSERT(getSize() == size * 4);
+	
 	glUniform4fv(getLocation(), size, &(const_cast<Vec4&>(x[0]))[0]);
 }
 
@@ -96,7 +95,8 @@ void ShaderProgramUniformVariable::set(const Mat3 x[], uint size) const
 {
 	doSanityChecks();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_MAT3);
-	ANKI_ASSERT(size > 0);
+	ANKI_ASSERT(getSize() == size);
+
 	glUniformMatrix3fv(getLocation(), size, true, &(x[0])[0]);
 }
 
@@ -106,19 +106,24 @@ void ShaderProgramUniformVariable::set(const Mat4 x[], uint size) const
 {
 	doSanityChecks();
 	ANKI_ASSERT(getGlDataType() == GL_FLOAT_MAT4);
-	ANKI_ASSERT(size > 0);
+	ANKI_ASSERT(getSize() == size);
+
 	glUniformMatrix4fv(getLocation(), size, true, &(x[0])[0]);
 }
 
 
 //==============================================================================
-void ShaderProgramUniformVariable::set(const Texture& tex, uint texUnit) const
+void ShaderProgramUniformVariable::set(const Texture& tex) const
 {
 	doSanityChecks();
-	ANKI_ASSERT(getGlDataType() == GL_SAMPLER_2D ||
-		getGlDataType() == GL_SAMPLER_2D_SHADOW);
-	tex.bind(texUnit);
-	glUniform1i(getLocation(), texUnit);
+	ANKI_ASSERT(getGlDataType() == GL_SAMPLER_2D 
+		|| getGlDataType() == GL_SAMPLER_2D_SHADOW);
+	
+	if(tex.getUnit() == -1)
+	{
+		tex.bind();
+	}
+	glUniform1i(getLocation(), tex.getUnit());
 }
 
 
@@ -128,10 +133,6 @@ void ShaderProgramUniformVariable::set(const Texture& tex, uint texUnit) const
 
 //==============================================================================
 
-#define SHADER_PROGRAM_EXCEPTION(x) ANKI_EXCEPTION( \
-	"Shader program \"" + rsrcFilename + \
-	"\": " + x)
-
 const char* ShaderProgram::stdSourceCode =
 	"#version 330 core\n"
 	//"precision lowp float;\n"
@@ -143,17 +144,129 @@ const char* ShaderProgram::stdSourceCode =
 	"#pragma debug(on)\n";
 #endif
 
+ShaderProgram* ShaderProgram::currentProgram = nullptr;
+
+
+//==============================================================================
+void ShaderProgram::create(const char* vertSource, const char* tcSource, 
+	const char* teSource, const char* geomSource, const char* fragSource,
+	const char* transformFeedbackVaryings[])
+{
+	ANKI_ASSERT(!isInitialized());
+
+	// 1) create and compile the shaders
+	//
+	std::string preprocSource = stdSourceCode;
+
+	ANKI_ASSERT(vertSource != nullptr);
+	vertShaderGlId = createAndCompileShader(vertSource, preprocSource.c_str(),
+		GL_VERTEX_SHADER);
+
+	if(tcSource != nullptr)
+	{
+		tcShaderGlId = createAndCompileShader(tcSource, preprocSource.c_str(), 
+			GL_TESS_CONTROL_SHADER);
+	}
+
+	if(teSource != nullptr)
+	{
+		teShaderGlId = createAndCompileShader(teSource, preprocSource.c_str(), 
+			GL_TESS_EVALUATION_SHADER);
+	}
+
+	if(geomSource != nullptr)
+	{
+		geomShaderGlId = createAndCompileShader(geomSource, preprocSource.c_str(), 
+			GL_GEOMETRY_SHADER);
+	}
+
+	ANKI_ASSERT(fragSource != nullptr);
+	fragShaderGlId = createAndCompileShader(fragSource, preprocSource.c_str(),
+		GL_FRAGMENT_SHADER);
+
+	// 2) create program and attach shaders
+	glId = glCreateProgram();
+	if(glId == 0)
+	{
+		throw ANKI_EXCEPTION("glCreateProgram failed");
+	}
+	glAttachShader(glId, vertShaderGlId);
+	glAttachShader(glId, fragShaderGlId);
+
+	if(tcSource != nullptr)
+	{
+		glAttachShader(glId, tcShaderGlId);
+	}
+
+	if(teSource != nullptr)
+	{
+		glAttachShader(glId, teShaderGlId);
+	}
+
+	if(geomSource != nullptr)
+	{
+		glAttachShader(glId, geomShaderGlId);
+	}
+
+	// 3) set the TRFFB varyings
+	ANKI_ASSERT(transformFeedbackVaryings != nullptr);
+	int count = 0;
+	while(*transformFeedbackVaryings != nullptr)
+	{
+		++count;
+		++transformFeedbackVaryings;
+	}
+
+	if(count)
+	{
+		glTransformFeedbackVaryings(glId,
+			count, 
+			transformFeedbackVaryings,
+			GL_SEPARATE_ATTRIBS);
+	}
+
+	// 4) link
+	link();
+
+	// init the rest
+	getUniAndAttribVars();
+}
 
 //==============================================================================
-ShaderProgram::~ShaderProgram()
+void ShaderProgram::destroy()
 {
-	/// @todo add code
+	if(vertShaderGlId != 0)
+	{
+		glDeleteShader(vertShaderGlId);
+	}
+
+	if(tcShaderGlId != 0)
+	{
+		glDeleteShader(tcShaderGlId);
+	}
+
+	if(teShaderGlId != 0)
+	{
+		glDeleteShader(teShaderGlId);
+	}
+
+	if(geomShaderGlId != 0)
+	{
+		glDeleteShader(geomShaderGlId);
+	}
+
+	if(fragShaderGlId != 0)
+	{
+		glDeleteShader(fragShaderGlId);
+	}
+
+	glDeleteProgram(glId);
 }
 
 
 //==============================================================================
-uint ShaderProgram::createAndCompileShader(const char* sourceCode,
-	const char* preproc, int type) const
+GLuint ShaderProgram::createAndCompileShader(const char* sourceCode,
+	const char* preproc, GLenum type)
 {
 	uint glId = 0;
 	const char* sourceStrs[2] = {NULL, NULL};
@@ -184,23 +297,8 @@ uint ShaderProgram::createAndCompileShader(const char* sourceCode,
 		glGetShaderInfoLog(glId, infoLen, &charsWritten, &infoLog[0]);
 		infoLog[charsWritten] = '\0';
 		
-		const char* shaderType = "*dummy*";
-		switch(type)
-		{
-			case GL_VERTEX_SHADER:
-				shaderType = "Vertex shader";
-				break;
-			case GL_FRAGMENT_SHADER:
-				shaderType = "Fragment shader";
-				break;
-			default:
-				ANKI_ASSERT(0); // Not supported
-		}
-		throw SHADER_PROGRAM_EXCEPTION(shaderType + 
-			" compiler error log follows:\n"
-			"===================================\n" +
-			&infoLog[0] +
-			"\n===================================\n" + sourceCode);
+		throw ANKI_EXCEPTION("Shader failed. Log:\n" + &infoLog[0]
+			+ "\nSource:\n" + sourceCode);
 	}
 
 	return glId;
@@ -227,8 +325,8 @@ void ShaderProgram::link() const
 
 		infoLogTxt.resize(info_len + 1);
 		glGetProgramInfoLog(glId, info_len, &charsWritten, &infoLogTxt[0]);
-		throw SHADER_PROGRAM_EXCEPTION("Link error log follows:\n" +
-			infoLogTxt);
+		throw ANKI_EXCEPTION("Link error log follows:\n" 
+			+ infoLogTxt);
 	}
 }
 
@@ -237,7 +335,7 @@ void ShaderProgram::link() const
 void ShaderProgram::getUniAndAttribVars()
 {
 	int num;
-	boost::array<char, 256> name_;
+	std::array<char, 256> name_;
 	GLsizei length;
 	GLint size;
 	GLenum type;
@@ -254,14 +352,14 @@ void ShaderProgram::getUniAndAttribVars()
 		int loc = glGetAttribLocation(glId, &name_[0]);
 		if(loc == -1) // if -1 it means that its an FFP var
 		{
-			ANKI_WARNING("Shader prog: \"" << rsrcFilename <<
-				"\": You are using FFP vertex attributes (\"" <<
-				&name_[0] << "\")");
+			ANKI_WARNING("You are using FFP vertex attributes (\"" 
+				<< &name_[0] << "\")");
 			continue;
 		}
 
 		ShaderProgramAttributeVariable* var =
-			new ShaderProgramAttributeVariable(loc, &name_[0], type, *this);
+			new ShaderProgramAttributeVariable(loc, &name_[0], type, 
+			size, this);
 
 		vars.push_back(var);
 		attribs.push_back(var);
@@ -281,14 +379,14 @@ void ShaderProgram::getUniAndAttribVars()
 		int loc = glGetUniformLocation(glId, &name_[0]);
 		if(loc == -1) // if -1 it means that its an FFP var
 		{
-			ANKI_WARNING("Shader prog: \"" << rsrcFilename <<
-				"\": You are using FFP vertex uniforms (\"" <<
-				&name_[0] << "\")");
+			ANKI_WARNING("You are using FFP vertex uniforms (\"" 
+				<< &name_[0] << "\")");
 			continue;
 		}
 
 		ShaderProgramUniformVariable* var =
-			new ShaderProgramUniformVariable(loc, &name_[0], type, *this);
+			new ShaderProgramUniformVariable(loc, &name_[0], type, 
+			size, this);
 
 		vars.push_back(var);
 		unis.push_back(var);
@@ -299,172 +397,54 @@ void ShaderProgram::getUniAndAttribVars()
 
 
 //==============================================================================
-void ShaderProgram::load(const char* filename)
-{
-	rsrcFilename = filename;
-	ANKI_ASSERT(!isInitialized());
-
-	ShaderProgramPrePreprocessor pars(filename);
-
-	// 1) create and compile the shaders
-	std::string preprocSource = stdSourceCode;
-	vertShaderGlId = createAndCompileShader(
-		pars.getShaderSource(ST_VERTEX).c_str(),
-		preprocSource.c_str(),
-		GL_VERTEX_SHADER);
-
-	fragShaderGlId = createAndCompileShader(
-		pars.getShaderSource(ST_FRAGMENT).c_str(),
-		preprocSource.c_str(),
-		GL_FRAGMENT_SHADER);
-
-	// 2) create program and attach shaders
-	glId = glCreateProgram();
-	if(glId == 0)
-	{
-		throw SHADER_PROGRAM_EXCEPTION("glCreateProgram failed");
-	}
-	glAttachShader(glId, vertShaderGlId);
-	glAttachShader(glId, fragShaderGlId);
-
-	// 3) set the TRFFB varyings
-	if(pars.getTranformFeedbackVaryings().size() > 0)
-	{
-		boost::array<const char*, 128> varsArr;
-		for(uint i = 0; i < pars.getTranformFeedbackVaryings().size(); i++)
-		{
-			varsArr[i] = pars.getTranformFeedbackVaryings()[i].c_str();
-		}
-		glTransformFeedbackVaryings(glId,
-			pars.getTranformFeedbackVaryings().size(), &varsArr[0],
-			GL_SEPARATE_ATTRIBS);
-	}
-
-	// 4) link
-	link();
-
-	// init the rest
-	getUniAndAttribVars();
-}
-
-
-//==============================================================================
-const ShaderProgramVariable& ShaderProgram::findVariableByName(
+const ShaderProgramVariable* ShaderProgram::findVariableByName(
 	const char* name) const
 {
 	NameToVarHashMap::const_iterator it = nameToVar.find(name);
 	if(it == nameToVar.end())
 	{
-		throw SHADER_PROGRAM_EXCEPTION("Cannot find variable: " + name);
+		return nullptr;
 	}
-	return *(it->second);
+	return it->second;
 }
 
 
 //==============================================================================
-const ShaderProgramAttributeVariable&
+const ShaderProgramAttributeVariable*
 	ShaderProgram::findAttributeVariableByName(const char* name) const
 {
 	NameToAttribVarHashMap::const_iterator it = nameToAttribVar.find(name);
 	if(it == nameToAttribVar.end())
 	{
-		throw SHADER_PROGRAM_EXCEPTION("Cannot find attribute loc: " + name);
+		return nullptr;
 	}
-	return *(it->second);
+	return it->second;
 }
 
 
 //==============================================================================
-const ShaderProgramUniformVariable& ShaderProgram::findUniformVariableByName(
+const ShaderProgramUniformVariable* ShaderProgram::findUniformVariableByName(
 	const char* name) const
 {
 	NameToUniVarHashMap::const_iterator it = nameToUniVar.find(name);
 	if(it == nameToUniVar.end())
 	{
-		throw SHADER_PROGRAM_EXCEPTION("Cannot find uniform loc: " + name);
+		return nullptr;
 	}
-	return *(it->second);
-}
-
-
-//==============================================================================
-bool ShaderProgram::variableExists(const char* name) const
-{
-	NameToVarHashMap::const_iterator it = nameToVar.find(name);
-	return it != nameToVar.end();
-}
-
-
-//==============================================================================
-bool ShaderProgram::uniformVariableExists(const char* name) const
-{
-	NameToUniVarHashMap::const_iterator it = nameToUniVar.find(name);
-	return it != nameToUniVar.end();
-}
-
-
-//==============================================================================
-bool ShaderProgram::attributeVariableExists(const char* name) const
-{
-	NameToAttribVarHashMap::const_iterator it = nameToAttribVar.find(name);
-	return it != nameToAttribVar.end();
-}
-
-
-//==============================================================================
-std::string ShaderProgram::createSrcCodeToCache(const char* sProgFPathName,
-	const char* preAppendedSrcCode)
-{
-	using namespace boost::filesystem;
-
-	if(strlen(preAppendedSrcCode) < 1)
-	{
-		return sProgFPathName;
-	}
-
-	// Create suffix
-	boost::hash<std::string> stringHash;
-	std::size_t h = stringHash(preAppendedSrcCode);
-	std::string suffix = boost::lexical_cast<std::string>(h);
-
-	//
-	path newfPathName = AppSingleton::get().getCachePath() /
-		(path(sProgFPathName).filename().string() + "." + suffix);
-
-	if(exists(newfPathName))
-	{
-		return newfPathName.string();
-	}
-
-	std::string src_ = Util::readFile(sProgFPathName);
-	std::string src = preAppendedSrcCode + src_;
-
-	std::ofstream f(newfPathName.string().c_str());
-	if(!f.is_open())
-	{
-		throw ANKI_EXCEPTION("Cannot open file for writing \"" +
-			newfPathName.string() + "\"");
-	}
-
-	f.write(src.c_str(), src.length());
-
-	return newfPathName.string();
+	return it->second;
 }
 
 
 //==============================================================================
 std::ostream& operator<<(std::ostream& s, const ShaderProgram& x)
 {
-	s << "ShaderProgram (" << x.rsrcFilename << ")\n";
+	s << "ShaderProgram\n";
 	s << "Variables:\n";
-	for(ShaderProgram::VariablesContainer::const_iterator it = x.vars.begin();
-		it != x.vars.end(); ++it)
+	for(const ShaderProgramVariable& var : x.vars)
 	{
-		const ShaderProgramVariable& var = *it;
-
-		s << var.getName() << " " << var.getLocation() << " " <<
-			(var.getType() == ShaderProgramVariable::T_ATTRIBUTE ? "[A]" :
-			"[U]") <<  '\n';
+		s << var.getName() << " " << var.getLocation() << " " 
+			<< (var.getType() == ShaderProgramVariable::SPVT_ATTRIBUTE 
+			? "[A]" : "[U]") <<  '\n';
 	}
 	return s;
 }

+ 102 - 70
anki/resource/ShaderProgram.h → anki/gl/ShaderProgram.h

@@ -1,15 +1,13 @@
-#ifndef ANKI_RESOURCE_SHADER_PROGRAM_H
-#define ANKI_RESOURCE_SHADER_PROGRAM_H
+#ifndef ANKI_GL_SHADER_PROGRAM_H
+#define ANKI_GL_SHADER_PROGRAM_H
 
 #include "anki/util/ConstCharPtrHashMap.h"
 #include "anki/util/Assert.h"
 #include "anki/math/Forward.h"
-#include "anki/gl/GlStateMachine.h"
 #include "anki/core/Globals.h"
 #include <boost/ptr_container/ptr_vector.hpp>
 #include <GL/glew.h>
 #include <vector>
-#include <boost/noncopyable.hpp>
 
 
 namespace anki {
@@ -20,20 +18,29 @@ class Texture;
 
 
 /// Shader program variable. The type is attribute or uniform
-class ShaderProgramVariable: public boost::noncopyable
+class ShaderProgramVariable
 {
 public:
 	/// Shader var types
-	enum Type
+	enum ShaderProgramVariableType
 	{
-		T_ATTRIBUTE,
-		T_UNIFORM
+		SPVT_ATTRIBUTE,
+		SPVT_UNIFORM
 	};
 
-	ShaderProgramVariable(GLint loc_, const char* name_,
-		GLenum glDataType_, Type type_, const ShaderProgram& fatherSProg_)
-		: loc(loc_), name(name_), glDataType(glDataType_), type(type_),
-			fatherSProg(fatherSProg_)
+	// Non-copyable
+	ShaderProgramVariable(const ShaderProgramVariable&) = delete;
+	ShaderProgramVariable& operator=(const ShaderProgramVariable&) = delete;
+
+	ShaderProgramVariable(
+		GLint loc_, 
+		const char* name_,
+		GLenum glDataType_, 
+		size_t size_,
+		ShaderProgramVariableType type_, 
+		const ShaderProgram* fatherSProg_)
+		: loc(loc_), name(name_), glDataType(glDataType_), size(size_), 
+			type(type_), fatherSProg(fatherSProg_)
 	{}
 
 	virtual ~ShaderProgramVariable()
@@ -41,9 +48,9 @@ public:
 
 	/// @name Accessors
 	/// @{
-	const ShaderProgram& getFatherSProg() const
+	const ShaderProgram& getFatherShaderProgram() const
 	{
-		return fatherSProg;
+		return *fatherSProg;
 	}
 
 	GLint getLocation() const
@@ -61,10 +68,15 @@ public:
 		return glDataType;
 	}
 
-	Type getType() const
+	ShaderProgramVariableType getType() const
 	{
 		return type;
 	}
+
+	size_t getSize() const
+	{
+		return size;
+	}
 	/// @}
 
 private:
@@ -73,9 +85,10 @@ private:
 	/// GL_FLOAT, GL_FLOAT_VEC2 etc. See
 	/// http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml
 	GLenum glDataType;
-	Type type; ///< @ref T_ATTRIBUTE or @ref T_UNIFORM
+	size_t size; ///< Its 1 if it is a single or >1 if it is an array
+	ShaderProgramVariableType type;
 	/// We need the ShaderProg of this variable mainly for sanity checks
-	const ShaderProgram& fatherSProg;
+	const ShaderProgram* fatherSProg;
 };
 
 
@@ -87,8 +100,10 @@ public:
 		int loc,
 		const char* name,
 		GLenum glDataType,
-		const ShaderProgram& fatherSProg)
-		: ShaderProgramVariable(loc, name, glDataType, T_UNIFORM, fatherSProg)
+		size_t size,
+		const ShaderProgram* fatherSProg)
+		: ShaderProgramVariable(loc, name, glDataType, size, SPVT_UNIFORM, 
+			fatherSProg)
 	{}
 
 	/// @name Set the var
@@ -111,7 +126,7 @@ public:
 	{
 		set(&x, 1);
 	}
-	void set(const Texture& tex, uint texUnit) const;
+	void set(const Texture& tex) const;
 
 	void set(const float x[], uint size) const;
 	void set(const Vec2 x[], uint size) const;
@@ -120,9 +135,10 @@ public:
 	void set(const Mat3 x[], uint size) const;
 	void set(const Mat4 x[], uint size) const;
 
-	/// @tparam Type float, Vec2, etc
-	template<typename Type>
-	void set(const std::vector<Type>& c)
+	/// @tparam Container It could be something like array<float, X> or 
+	///         vector<Vec2> etc
+	template<typename Container>
+	void set(const Container& c) const
 	{
 		set(&c[0], c.size());
 	}
@@ -142,9 +158,9 @@ class ShaderProgramAttributeVariable: public ShaderProgramVariable
 {
 public:
 	ShaderProgramAttributeVariable(
-		int loc_, const char* name_, GLenum glDataType_,
-		const ShaderProgram& fatherSProg_)
-		: ShaderProgramVariable(loc_, name_, glDataType_, T_ATTRIBUTE,
+		int loc_, const char* name_, GLenum glDataType_, size_t size,
+		const ShaderProgram* fatherSProg_)
+		: ShaderProgramVariable(loc_, name_, glDataType_, size, SPVT_ATTRIBUTE,
 			fatherSProg_)
 	{}
 };
@@ -152,12 +168,11 @@ public:
 
 /// Shader program resource
 ///
-/// Shader program. Combines a fragment and a vertex shader. Every shader
-/// program consist of one OpenGL ID, a vector of uniform variables and a
-/// vector of attribute variables. Every variable is a struct that contains
-/// the variable's name, location, OpenGL data type and if it is a uniform or
-/// an attribute var.
-class ShaderProgram: public boost::noncopyable
+/// Shader program. Combines. Every shader program consist of one OpenGL ID, a 
+/// vector of uniform variables and a vector of attribute variables. Every 
+/// variable is a struct that contains the variable's name, location, OpenGL 
+/// data type and if it is a uniform or an attribute var.
+class ShaderProgram
 {
 public:
 	typedef boost::ptr_vector<ShaderProgramVariable> VariablesContainer;
@@ -166,13 +181,28 @@ public:
 	typedef std::vector<ShaderProgramAttributeVariable*>
 		AttributeVariablesContainer;
 
+	// Non-copyable
+	ShaderProgram(const ShaderProgram&) = delete;
+	ShaderProgram& operator=(const ShaderProgram&) = delete;
+
 	ShaderProgram()
 	{
-		glId = vertShaderGlId = tcShaderGlId = teShaderGlId =
-			geomShaderGlId = fragShaderGlId = UNINITIALIZED_ID;
+		init();
 	}
 
-	~ShaderProgram();
+	ShaderProgram(const char* vertSource, const char* tcSource, 
+		const char* teSource, const char* geomSource, const char* fragSource,
+		const char* transformFeedbackVaryings[])
+	{
+		init();
+		create(vertSource, tcSource, teSource, geomSource, fragSource,
+			transformFeedbackVaryings);
+	}
+
+	~ShaderProgram()
+	{
+		destroy();
+	}
 
 	/// @name Accessors
 	/// @{
@@ -199,49 +229,43 @@ public:
 	}
 	/// @}
 
-	/// Resource load
-	void load(const char* filename);
+	/// Create the program
+	/// @param vertSource Vertex shader source
+	/// @param tcSource Tessellation control shader source. Can be nullptr
+	/// @param teSource Tessellation evaluation shader source. Can be nullptr
+	/// @param geomSource Geometry shader source. Can be nullptr
+	/// @param fragSource Fragment shader source. Can be nullptr
+	/// @param transformFeedbackVaryings A list of varyings names. Eg 
+	///                                  {"var0", "var1", nullptr} or {nullptr}
+	void create(const char* vertSource, const char* tcSource, 
+		const char* teSource, const char* geomSource, const char* fragSource,
+		const char* transformFeedbackVaryings[]);
 
 	/// Bind the shader program
-	void bind() const
+	void bind()
 	{
 		ANKI_ASSERT(isInitialized());
-		GlStateMachineSingleton::get().useShaderProg(glId);
+		if(currentProgram == nullptr || currentProgram != this)
+		{
+			glUseProgram(glId);
+			currentProgram = this;
+		}
 	}
 
 	/// @name Variable finders
-	/// Used to find and return the variable. They throw exception if
-	/// variable not found so ask if the variable with that name exists
-	/// prior using any of these
+	/// Used to find and return the variable. They return nullptr if the 
+	/// variable is not found
 	/// @{
-	const ShaderProgramVariable& findVariableByName(const char* varName) const;
-	const ShaderProgramUniformVariable& findUniformVariableByName(
+	const ShaderProgramVariable* findVariableByName(const char* varName) const;
+	const ShaderProgramUniformVariable* findUniformVariableByName(
 		const char* varName) const;
-	const ShaderProgramAttributeVariable& findAttributeVariableByName(
+	const ShaderProgramAttributeVariable* findAttributeVariableByName(
 		const char* varName) const;
 	/// @}
 
-	/// @name Check for variable existance
-	/// @{
-	bool variableExists(const char* varName) const;
-	bool uniformVariableExists(const char* varName) const;
-	bool attributeVariableExists(const char* varName) const;
-	/// @}
-
-	/// Used by @ref Material and @ref Renderer to create custom shaders in
-	/// the cache
-	/// @param sProgFPathName The file pathname of the shader prog
-	/// @param preAppendedSrcCode The source code we want to write on top
-	/// of the shader prog
-	/// @return The file pathname of the new shader prog. Its
-	/// $HOME/.anki/cache/newFNamePrefix_fName
-	static std::string createSrcCodeToCache(const char* sProgFPathName,
-		const char* preAppendedSrcCode);
-
-	/// For sorting
-	bool operator<(const ShaderProgram& b) const
+	static ShaderProgram* getCurrentProgram()
 	{
-		return glId < b.glId;
+		return currentProgram;
 	}
 
 	/// For debugging
@@ -258,9 +282,9 @@ private:
 	typedef ConstCharPtrHashMap<ShaderProgramAttributeVariable*>::Type
 		NameToAttribVarHashMap;
 
-	static const GLuint UNINITIALIZED_ID = -1;
+	/// Is an optimization. it keeps the program that is now binded 
+	static ShaderProgram* currentProgram;
 
-	std::string rsrcFilename;
 	GLuint glId; ///< The OpenGL ID of the shader program
 	GLuint vertShaderGlId; ///< Vertex shader OpenGL id
 	GLuint tcShaderGlId; ///< Tessellation control shader OpenGL id
@@ -289,8 +313,8 @@ private:
 	/// Create and compile shader
 	/// @return The shader's OpenGL id
 	/// @exception Exception
-	uint createAndCompileShader(const char* sourceCode,
-		const char* preproc, int type) const;
+	static GLuint createAndCompileShader(const char* sourceCode,
+		const char* preproc, GLenum type);
 
 	/// Link the shader program
 	/// @exception Exception
@@ -299,8 +323,16 @@ private:
 	/// Returns true if the class points to a valid GL ID
 	bool isInitialized() const
 	{
-		return glId != UNINITIALIZED_ID;
+		return glId != 0;
 	}
+
+	void init()
+	{
+		glId = vertShaderGlId = tcShaderGlId = teShaderGlId =
+			geomShaderGlId = fragShaderGlId = 0;
+	}
+
+	void destroy();
 }; 
 
 

+ 226 - 0
anki/gl/Texture.cpp

@@ -0,0 +1,226 @@
+#include "anki/gl/Texture.h"
+#include "anki/gl/GlException.h"
+#include "anki/util/Exception.h"
+#include <boost/lexical_cast.hpp>
+
+
+namespace anki {
+
+
+//==============================================================================
+// TextureManager                                                              =
+//==============================================================================
+
+//==============================================================================
+TextureManager::TextureManager()
+{
+	GLint tmp;
+	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &tmp);
+	units.resize(tmp - 1, nullptr);
+	
+	activeUnit = -1;
+	mipmapping = true;
+	anisotropyLevel = 8;
+	compression = true;
+}
+
+
+//==============================================================================
+void TextureManager::activateUnit(uint unit)
+{
+	ANKI_ASSERT(unit < units.size());
+	if(activeUnit == unit)
+	{
+		return;
+	}
+
+	activeUnit = unit;
+	glActiveTexture(GL_TEXTURE0 + activeUnit);
+}
+
+
+//==============================================================================
+uint TextureManager::choseUnit(Texture* tex)
+{
+	// Already binded
+	//
+	if(tex->unit != -1)
+	{
+		ANKI_ASSERT(units[tex->unit] == tex);
+		return tex->unit;
+	}
+
+	// Find an empty slot for it
+	//
+	for(uint i = 0; i < units.size(); i++)
+	{
+		if(units[i] == nullptr)
+		{
+			units[i] = tex;
+			return i;
+		}
+	}
+
+	// If all units occupied chose a random for now
+	//
+	int tmp = rand() % units.size();
+	units[tmp]->unit = -1;
+	units[tmp] = tex;
+	return tmp;
+}
+
+
+//==============================================================================
+void TextureManager::textureDeleted(Texture* tex)
+{
+	for(auto it = units.begin(); it != units.end(); ++it)
+	{
+		if(*it == tex)
+		{
+			*it = nullptr;
+			return;
+		}
+	}
+	ANKI_ASSERT(0 && "Pointer not found");
+}
+
+
+//==============================================================================
+// Texture                                                                     =
+//==============================================================================
+
+//==============================================================================
+Texture::Texture()
+	: glId(std::numeric_limits<uint>::max()), target(GL_TEXTURE_2D), unit(-1)
+{}
+
+
+//==============================================================================
+Texture::~Texture()
+{
+	if(isLoaded())
+	{
+		glDeleteTextures(1, &glId);
+	}
+
+	TextureManagerSingleton::get().textureDeleted(this);
+}
+
+
+//==============================================================================
+void Texture::create(const Initializer& init)
+{
+	TextureManagerSingleton::get().lock();
+
+	// Sanity checks
+	//
+	ANKI_ASSERT(!isLoaded());
+	ANKI_ASSERT(init.internalFormat <= 4 && "Deprecated internal format");
+
+	// Create
+	//
+	glGenTextures(1, &glId);
+	target = GL_TEXTURE_2D;
+	internalFormat = init.internalFormat;
+	format = init.format;
+	type = init.type;
+	width = init.width;
+	height = init.height;
+
+	// Bind
+	glActiveTexture(GL_TEXTURE0 
+		+ TextureManagerSingleton::get().getMaxUnitsCount() - 1);
+	glBindTexture(target, glId);
+
+	switch(internalFormat)
+	{
+	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+		glCompressedTexImage2D(target, 0, internalFormat,
+			width, height, 0, init.dataSize, init.data);
+		break;
+
+	default:
+		glTexImage2D(target, 0, internalFormat, width,
+			height, 0, format, type, init.data);
+	}
+
+	if(init.repeat)
+	{
+		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
+		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
+	}
+	else
+	{
+		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	}
+
+	if(init.mipmapping && init.data)
+	{
+		glGenerateMipmap(target);
+	}
+
+	// If not mipmapping then the filtering cannot be trilinear
+	if(init.filteringType == TFT_TRILINEAR && !init.mipmapping)
+	{
+		setFilteringNoBind(TFT_LINEAR);
+	}
+	else
+	{
+		setFilteringNoBind(init.filteringType);
+	}
+
+	if(init.anisotropyLevel > 1)
+	{
+		glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 
+			GLint(init.anisotropyLevel));
+	}
+
+	TextureManagerSingleton::get().unlock();
+
+	ANKI_CHECK_GL_ERROR();
+}
+
+
+//==============================================================================
+void Texture::bind() const
+{
+	unit = TextureManagerSingleton::get().choseUnit(
+		const_cast<Texture*>(this));
+
+	TextureManagerSingleton::get().activateUnit(unit);
+	glBindTexture(target, glId);
+}
+
+
+//==============================================================================
+void Texture::genMipmap()
+{
+	bind();
+	glGenerateMipmap(target);
+}
+
+
+//==============================================================================
+void Texture::setFilteringNoBind(TextureFilteringType filterType) const
+{
+	switch(filterType)
+	{
+	case TFT_NEAREST:
+		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		break;
+	case TFT_LINEAR:
+		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		break;
+	case TFT_TRILINEAR:
+		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	}
+}
+
+
+} // end namespace

+ 216 - 0
anki/gl/Texture.h

@@ -0,0 +1,216 @@
+#ifndef ANKI_GL_TEXTURE_H
+#define ANKI_GL_TEXTURE_H
+
+#include "anki/util/StdTypes.h"
+#include "anki/util/Assert.h"
+#include "anki/util/Singleton.h"
+#include <cstdlib>
+#include <GL/glew.h>
+#include <vector>
+#include <limits>
+#include <thread>
+
+
+namespace anki {
+
+
+class Texture;
+
+
+/// XXX
+class TextureManager
+{
+public:
+	TextureManager();
+
+	/// @name Accessors
+	/// @{
+	uint getAnisotropyLevel() const
+	{
+		return anisotropyLevel;
+	}
+	void setAnisotropyLevel(uint x) 
+	{
+		anisotropyLevel = x;
+	}
+
+	bool getMipmappingEnabled() const
+	{
+		return mipmapping;
+	}
+	void setMipmappingEnabled(bool x) 
+	{
+		mipmapping = x;
+	}
+
+	bool getCompressionEnabled() const
+	{
+		return compression;
+	}
+	void setCompressionEnabled(bool x) 
+	{
+		compression = x;
+	}
+
+	size_t getMaxUnitsCount() const
+	{
+		return units.size() + 1;
+	}
+	/// @}
+
+	/// The manager returns the texture unit where the @a tex can be binded
+	uint choseUnit(Texture* tex);
+
+	/// Alias for glActiveTexture
+	void activateUnit(uint unit);
+
+	/// This is called by the texture destructor in order to invalidate the 
+	/// texture
+	void textureDeleted(Texture* tex);
+
+	void lock()
+	{
+		mtx.lock();
+	}
+	void unlock()
+	{
+		mtx.unlock();
+	}
+
+private:
+	/// Texture units. The last is reserved and only used in Texture::create
+	std::vector<Texture*> units;
+	std::mutex mtx; ///< A mutex that locks the texture manager
+	uint activeUnit;
+
+	/// @name Hints
+	/// Hints when creating new textures. The implementation may try to ignore 
+	/// them
+	/// @{
+	uint anisotropyLevel;
+	bool mipmapping;
+	/// If true the new textures will be compressed if not already
+	bool compression;
+	/// @}
+};
+
+
+/// The global texture manager
+typedef Singleton<TextureManager> TextureManagerSingleton;
+
+
+/// Texture class
+///
+/// @note ITS NOT THREAD SAFE
+class Texture
+{
+	friend class TextureManager;
+
+public:
+	enum TextureFilteringType
+	{
+		TFT_NEAREST,
+		TFT_LINEAR,
+		TFT_TRILINEAR
+	};
+
+	/// Texture initializer struct
+	struct Initializer
+	{
+		uint width;
+		uint height;
+		GLint internalFormat;
+		GLenum format;
+		GLenum type;
+		const void* data;
+		bool mipmapping;
+		TextureFilteringType filteringType;
+		bool repeat;
+		int anisotropyLevel;
+		size_t dataSize; ///< For compressed textures
+	};
+
+	/// Default constructor
+	Texture();
+
+	/// Desrcuctor
+	~Texture();
+
+	/// @name Accessors
+	/// @{
+	GLuint getGlId() const
+	{
+		ANKI_ASSERT(isLoaded());
+		return glId;
+	}
+
+	GLenum getInternalFormat() const
+	{
+		ANKI_ASSERT(isLoaded());
+		return internalFormat;
+	}
+
+	GLenum getFormat() const
+	{
+		ANKI_ASSERT(isLoaded());
+		return format;
+	}
+
+	GLenum getType() const
+	{
+		ANKI_ASSERT(isLoaded());
+		return type;
+	}
+
+	int getUnit() const
+	{
+		return unit;
+	}
+
+	GLuint getWidth() const
+	{
+		return width;
+	}
+
+	GLuint getHeight() const
+	{
+		return height;
+	}
+	/// @}
+
+	/// Create a texture
+	void create(const Initializer& init);
+
+	void bind() const;
+	void setFiltering(TextureFilteringType filterType)
+	{
+		bind();
+		setFilteringNoBind(filterType);
+	}
+	void genMipmap();
+
+private:
+	GLuint glId; ///< Identification for OGL
+	GLuint target; ///< GL_TEXTURE_2D, GL_TEXTURE_3D... etc
+	GLuint internalFormat; ///< GL_COMPRESSED_RED, GL_RGB16 etc
+	GLuint format; ///< GL_RED, GL_RG, GL_RGB etc
+	GLuint type; ///< GL_UNSIGNED_BYTE, GL_BYTE etc
+	GLuint width, height;
+
+	/// The texure unit that its binded to. It's -1 if it's not binded to any
+	/// texture unit
+	mutable int unit; 
+
+	bool isLoaded() const
+	{
+		return glId != std::numeric_limits<uint>::max();
+	}
+
+	void setFilteringNoBind(TextureFilteringType filterType) const;
+};
+
+
+} // end namespace
+
+
+#endif

+ 2 - 1
anki/gl/TimeQuery.cpp

@@ -3,7 +3,8 @@
 #include "anki/gl/GlException.h"
 
 
-namespace anki {
+namespace anki
+{
 
 
 //==============================================================================

+ 2 - 1
anki/gl/TimeQuery.h

@@ -5,7 +5,8 @@
 #include <boost/array.hpp>
 
 
-namespace anki {
+namespace anki
+{
 
 
 /// Used to profile the GPU. It gets the time elapsed from when the begin() is

+ 1 - 1
anki/gl/Vao.cpp

@@ -1,7 +1,7 @@
 #include "anki/gl/Vao.h"
 #include "anki/gl/Vbo.h"
 #include "anki/util/Exception.h"
-#include "anki/resource/ShaderProgram.h"
+#include "anki/gl/ShaderProgram.h"
 
 
 namespace anki {

+ 19 - 16
anki/gl/Vao.h

@@ -5,7 +5,6 @@
 #include "anki/util/Assert.h"
 #include "anki/gl/GlException.h"
 #include <GL/glew.h>
-#include <boost/noncopyable.hpp>
 
 
 namespace anki {
@@ -16,9 +15,13 @@ class Vbo;
 
 
 /// Vertex array object. Non-copyable to avoid instantiating it in the stack
-class Vao: public boost::noncopyable
+class Vao
 {
 public:
+	// Non-copyable
+	Vao(const Vao&) = delete;
+	Vao& operator=(const Vao&) = delete;
+
 	/// @name Constructors
 	/// @{
 
@@ -70,13 +73,13 @@ public:
 	/// @param pointer Specifies a offset of the first component of the
 	///        first generic vertex attribute in the array
 	void attachArrayBufferVbo(
-		const Vbo& vbo,
-		const ShaderProgramAttributeVariable& attribVar,
-		GLint size,
-		GLenum type,
-		GLboolean normalized,
-		GLsizei stride,
-		const GLvoid* pointer);
+	    const Vbo& vbo,
+	    const ShaderProgramAttributeVariable& attribVar,
+	    GLint size,
+	    GLenum type,
+	    GLboolean normalized,
+	    GLsizei stride,
+	    const GLvoid* pointer);
 
 	/// Attach an array buffer VBO. See @link
 	/// http://www.opengl.org/sdk/docs/man3/xhtml/glVertexAttribPointer.xml
@@ -93,13 +96,13 @@ public:
 	/// @param pointer Specifies a offset of the first component of the
 	///        first generic vertex attribute in the array
 	void attachArrayBufferVbo(
-		const Vbo& vbo,
-		uint attribVarLocation,
-		GLint size,
-		GLenum type,
-		GLboolean normalized,
-		GLsizei stride,
-		const GLvoid* pointer);
+	    const Vbo& vbo,
+	    uint attribVarLocation,
+	    GLint size,
+	    GLenum type,
+	    GLboolean normalized,
+	    GLsizei stride,
+	    const GLvoid* pointer);
 
 	/// Attach an element array buffer VBO
 	void attachElementArrayBufferVbo(const Vbo& vbo);

+ 2 - 2
anki/gl/Vbo.h

@@ -37,8 +37,8 @@ public:
 		GLenum usage)
 	{
 		// unacceptable target_
-		ANKI_ASSERT(target == GL_ARRAY_BUFFER ||
-			target == GL_ELEMENT_ARRAY_BUFFER);
+		ANKI_ASSERT(target == GL_ARRAY_BUFFER
+			|| target == GL_ELEMENT_ARRAY_BUFFER);
 		BufferObject::create(target, sizeInBytes, dataPtr, usage);
 	}
 };

+ 10 - 10
anki/math/Axisang.inl.h

@@ -46,15 +46,15 @@ inline Axisang::Axisang(const Quat& q)
 // constructor [mat3]
 inline Axisang::Axisang(const Mat3& m3)
 {
-	if((fabs(m3(0, 1) - m3(1, 0)) < Math::EPSILON) &&
-		(fabs(m3(0, 2) - m3(2, 0)) < Math::EPSILON) &&
-		(fabs(m3(1, 2) - m3(2, 1)) < Math::EPSILON))
+	if((fabs(m3(0, 1) - m3(1, 0)) < Math::EPSILON) 
+		&&(fabs(m3(0, 2) - m3(2, 0)) < Math::EPSILON) 
+		&& (fabs(m3(1, 2) - m3(2, 1)) < Math::EPSILON))
 	{
 
-		if((fabs(m3(0, 1) + m3(1, 0)) < 0.1) &&
-			(fabs(m3(0, 2) + m3(2, 0)) < 0.1) &&
-			(fabs(m3(1, 2) + m3(2, 1)) < 0.1) &&
-			(fabs(m3(0, 0) + m3(1, 1) + m3(2, 2)) - 3) < 0.1)
+		if((fabs(m3(0, 1) + m3(1, 0)) < 0.1) 
+			&& (fabs(m3(0, 2) + m3(2, 0)) < 0.1) 
+			&& (fabs(m3(1, 2) + m3(2, 1)) < 0.1) 
+			&& (fabs(m3(0, 0) + m3(1, 1) + m3(2, 2)) - 3) < 0.1)
 		{
 			axis = Vec3(1.0, 0.0, 0.0);
 			ang = 0.0;
@@ -122,9 +122,9 @@ inline Axisang::Axisang(const Mat3& m3)
 		return;
 	}
 
-	float s = Math::sqrt((m3(2, 1) - m3(1, 2)) * (m3(2, 1) - m3(1, 2)) +
-		(m3(0, 2) - m3(2, 0)) * (m3(0, 2) - m3(2, 0)) +
-		(m3(1, 0) - m3(0, 1)) * (m3(1, 0) - m3(0, 1)));
+	float s = Math::sqrt((m3(2, 1) - m3(1, 2)) * (m3(2, 1) - m3(1, 2)) 
+		+ (m3(0, 2) - m3(2, 0)) * (m3(0, 2) - m3(2, 0)) 
+		+ (m3(1, 0) - m3(0, 1)) * (m3(1, 0) - m3(0, 1)));
 
 	if(fabs(s) < 0.001)
 	{

+ 1 - 1
anki/math/Euler.h

@@ -56,7 +56,7 @@ private:
 			float x, y, z;
 		} vec;
 
-		boost::array<float, 3> arr;
+		std::array<float, 3> arr;
 	};
 	/// @}
 };

+ 3 - 3
anki/math/Mat3.h

@@ -23,7 +23,7 @@ public:
 		const float m10, const float m11, const float m12,
 		const float m20, const float m21, const float m22);
 	explicit Mat3(const float arr[]);
-			 Mat3(const Mat3& b);
+	Mat3(const Mat3& b);
 	explicit Mat3(const Quat& q); ///< Quat to Mat3. 12 muls, 12 adds
 	explicit Mat3(const Euler& eu);
 	explicit Mat3(const Axisang& axisang);
@@ -118,8 +118,8 @@ private:
 	/// @{
 	union
 	{
-		boost::array<float, 9> arr1;
-		boost::array<boost::array<float, 3>, 3> arr2;
+		std::array<float, 9> arr1;
+		std::array<std::array<float, 3>, 3> arr2;
 	};
 	/// @}
 };

+ 3 - 3
anki/math/Mat3.inl.h

@@ -132,7 +132,8 @@ inline Mat3::Mat3(const Axisang& axisang)
 	tmp1 = axis.x() * axis.z() * t;
 	tmp2 = axis.y() * s;
 	(*this)(2, 0) = tmp1 - tmp2;
-	(*this)(0, 2) = tmp1 + tmp2;    tmp1 = axis.y() * axis.z() * t;
+	(*this)(0, 2) = tmp1 + tmp2;
+	tmp1 = axis.y() * axis.z() * t;
 	tmp2 = axis.x() * s;
 	(*this)(2, 1) = tmp1 + tmp2;
 	(*this)(1, 2) = tmp1 - tmp2;
@@ -395,8 +396,7 @@ inline Vec3 Mat3::operator*(const Vec3& b) const
 	return Vec3(
 		(*this)(0, 0) * b.x() + (*this)(0, 1) * b.y() + (*this)(0, 2) * b.z(),
 		(*this)(1, 0) * b.x() + (*this)(1, 1) * b.y() + (*this)(1, 2) * b.z(),
-		(*this)(2, 0) * b.x() + (*this)(2, 1) * b.y() + (*this)(2, 2) * b.z()
-	);
+		(*this)(2, 0) * b.x() + (*this)(2, 1) * b.y() + (*this)(2, 2) * b.z());
 }
 
 

+ 4 - 4
anki/math/Mat4.h

@@ -26,7 +26,7 @@ public:
 		const float m30, const float m31, const float m32,
 		const float m33);
 	explicit Mat4(const float arr[]);
-			 Mat4(const Mat4& b);
+	Mat4(const Mat4& b);
 	explicit Mat4(const Mat3& m3);
 	explicit Mat4(const Vec3& v);
 	explicit Mat4(const Vec4& v);
@@ -123,10 +123,10 @@ private:
 	/// @{
 	union
 	{
-		boost::array<float, 16> arr1;
-		boost::array<boost::array<float, 4>, 4> arr2;
+		std::array<float, 16> arr1;
+		std::array<std::array<float, 4>, 4> arr2;
 #if defined(ANKI_MATH_INTEL_SIMD)
-		boost::array<__m128, 4> arrMm;
+		std::array<__m128, 4> arrMm;
 #endif
 	};
 	/// @}

+ 51 - 44
anki/math/Mat4.inl.h

@@ -332,8 +332,8 @@ inline Mat4 Mat4::operator*(const Mat4& b) const
 	{
 		for(int j = 0; j < 4; j++)
 		{
-			c(i, j) = (*this)(i, 0) * b(0, j) + (*this)(i, 1) * b(1, j) +
-				(*this)(i, 2) * b(2, j) + (*this)(i, 3) * b(3, j);
+			c(i, j) = (*this)(i, 0) * b(0, j) + (*this)(i, 1) * b(1, j) 
+				+ (*this)(i, 2) * b(2, j) + (*this)(i, 3) * b(3, j);
 		}
 	}
 #endif
@@ -560,14 +560,21 @@ inline Vec4 Mat4::operator*(const Vec4& b) const
 	}
 	return v;
 #else
-	return Vec4((*this)(0, 0) * b.x() + (*this)(0, 1) * b.y() +
-		(*this)(0, 2) * b.z() + (*this)(0, 3) * b.w(),
-		(*this)(1, 0) * b.x() + (*this)(1, 1) * b.y() +
-		(*this)(1, 2) * b.z() + (*this)(1, 3) * b.w(),
-		(*this)(2, 0) * b.x() + (*this)(2, 1) * b.y() +
-		(*this)(2, 2) * b.z() + (*this)(2, 3) * b.w(),
-		(*this)(3, 0) * b.x() + (*this)(3, 1) * b.y() +
-		(*this)(3, 2) * b.z() + (*this)(3, 3) * b.w());
+	Vec4 out;
+
+	out.x() = (*this)(0, 0) * b.x() + (*this)(0, 1) * b.y() 
+		+ (*this)(0, 2) * b.z() + (*this)(0, 3) * b.w();
+
+	out.y() = (*this)(1, 0) * b.x() + (*this)(1, 1) * b.y() 
+		+ (*this)(1, 2) * b.z() + (*this)(1, 3) * b.w();
+
+	out.z() = (*this)(2, 0) * b.x() + (*this)(2, 1) * b.y() 
+		+ (*this)(2, 2) * b.z() + (*this)(2, 3) * b.w();
+
+	out.w() = (*this)(3, 0) * b.x() + (*this)(3, 1) * b.y() 
+		+ (*this)(3, 2) * b.z() + (*this)(3, 3) * b.w();
+
+	return out;
 #endif
 }
 
@@ -784,30 +791,30 @@ inline const Mat4& Mat4::getZero()
 inline float Mat4::getDet() const
 {
 	const Mat4& t = *this;
-	return t(0, 3) * t(1, 2) * t(2, 1) * t(3, 0) -
-		t(0, 2) * t(1, 3) * t(2, 1) * t(3, 0) -
-		t(0, 3) * t(1, 1) * t(2, 2) * t(3, 0) +
-		t(0, 1) * t(1, 3) * t(2, 2) * t(3, 0) +
-		t(0, 2) * t(1, 1) * t(2, 3) * t(3, 0) -
-		t(0, 1) * t(1, 2) * t(2, 3) * t(3, 0) -
-		t(0, 3) * t(1, 2) * t(2, 0) * t(3, 1) +
-		t(0, 2) * t(1, 3) * t(2, 0) * t(3, 1) +
-		t(0, 3) * t(1, 0) * t(2, 2) * t(3, 1) -
-		t(0, 0) * t(1, 3) * t(2, 2) * t(3, 1) -
-		t(0, 2) * t(1, 0) * t(2, 3) * t(3, 1) +
-		t(0, 0) * t(1, 2) * t(2, 3) * t(3, 1) +
-		t(0, 3) * t(1, 1) * t(2, 0) * t(3, 2) -
-		t(0, 1) * t(1, 3) * t(2, 0) * t(3, 2) -
-		t(0, 3) * t(1, 0) * t(2, 1) * t(3, 2) +
-		t(0, 0) * t(1, 3) * t(2, 1) * t(3, 2) +
-		t(0, 1) * t(1, 0) * t(2, 3) * t(3, 2) -
-		t(0, 0) * t(1, 1) * t(2, 3) * t(3, 2) -
-		t(0, 2) * t(1, 1) * t(2, 0) * t(3, 3) +
-		t(0, 1) * t(1, 2) * t(2, 0) * t(3, 3) +
-		t(0, 2) * t(1, 0) * t(2, 1) * t(3, 3) -
-		t(0, 0) * t(1, 2) * t(2, 1) * t(3, 3) -
-		t(0, 1) * t(1, 0) * t(2, 2) * t(3, 3) +
-		t(0, 0) * t(1, 1) * t(2, 2) * t(3, 3);
+	return t(0, 3) * t(1, 2) * t(2, 1) * t(3, 0) 
+		- t(0, 2) * t(1, 3) * t(2, 1) * t(3, 0) 
+		- t(0, 3) * t(1, 1) * t(2, 2) * t(3, 0) 
+		+ t(0, 1) * t(1, 3) * t(2, 2) * t(3, 0)
+		+ t(0, 2) * t(1, 1) * t(2, 3) * t(3, 0) 
+		- t(0, 1) * t(1, 2) * t(2, 3) * t(3, 0) 
+		- t(0, 3) * t(1, 2) * t(2, 0) * t(3, 1) 
+		+ t(0, 2) * t(1, 3) * t(2, 0) * t(3, 1) 
+		+ t(0, 3) * t(1, 0) * t(2, 2) * t(3, 1) 
+		- t(0, 0) * t(1, 3) * t(2, 2) * t(3, 1)
+		- t(0, 2) * t(1, 0) * t(2, 3) * t(3, 1) 
+		+ t(0, 0) * t(1, 2) * t(2, 3) * t(3, 1) 
+		+ t(0, 3) * t(1, 1) * t(2, 0) * t(3, 2) 
+		- t(0, 1) * t(1, 3) * t(2, 0) * t(3, 2)
+		- t(0, 3) * t(1, 0) * t(2, 1) * t(3, 2)
+		+ t(0, 0) * t(1, 3) * t(2, 1) * t(3, 2) 
+		+ t(0, 1) * t(1, 0) * t(2, 3) * t(3, 2)
+		- t(0, 0) * t(1, 1) * t(2, 3) * t(3, 2)
+		- t(0, 2) * t(1, 1) * t(2, 0) * t(3, 3)
+		+ t(0, 1) * t(1, 2) * t(2, 0) * t(3, 3)
+		+ t(0, 2) * t(1, 0) * t(2, 1) * t(3, 3)
+		- t(0, 0) * t(1, 2) * t(2, 1) * t(3, 3) 
+		- t(0, 1) * t(1, 0) * t(2, 2) * t(3, 3) 
+		+ t(0, 0) * t(1, 1) * t(2, 2) * t(3, 3);
 }
 
 
@@ -879,8 +886,8 @@ inline Mat4 Mat4::getInverse() const
 	m4(3, 3) = tmp[10] * in(2, 2) + tmp[4] * in(0, 2) + tmp[9] * in(1, 2);
 	m4(3, 3)-= tmp[8] * in(1, 2) + tmp[11] * in(2, 2) + tmp[5] * in(0, 2);
 
-	det = (*this)(0, 0) * m4(0, 0) + (*this)(1, 0) * m4(0, 1) +
-		(*this)(2, 0) * m4(0, 2) + (*this)(3, 0) * m4(0, 3);
+	det = (*this)(0, 0) * m4(0, 0) + (*this)(1, 0) * m4(0, 1) 
+		+ (*this)(2, 0) * m4(0, 2) + (*this)(3, 0) * m4(0, 3);
 
 	ANKI_ASSERT(!Math::isZero(det)); // Cannot invert, det == 0
 	det = 1.0 / det;
@@ -934,8 +941,8 @@ inline Mat4 Mat4::combineTransformations(const Mat4& m0, const Mat4& m1)
 	*/
 
 	// one of the 2 mat4 doesnt represent transformation
-	ANKI_ASSERT(Math::isZero(m0(3, 0) + m0(3, 1) + m0(3, 2) + m0(3, 3)-1.0) &&
-		Math::isZero(m1(3, 0) + m1(3, 1) + m1(3, 2) + m1(3, 3)-1.0));
+	ANKI_ASSERT(Math::isZero(m0(3, 0) + m0(3, 1) + m0(3, 2) + m0(3, 3)-1.0) 
+		&& Math::isZero(m1(3, 0) + m1(3, 1) + m1(3, 2) + m1(3, 3)-1.0));
 
 	Mat4 m4;
 
@@ -949,14 +956,14 @@ inline Mat4 Mat4::combineTransformations(const Mat4& m0, const Mat4& m1)
 	m4(2, 1) = m0(2, 0) * m1(0, 1) + m0(2, 1) * m1(1, 1) + m0(2, 2) * m1(2, 1);
 	m4(2, 2) = m0(2, 0) * m1(0, 2) + m0(2, 1) * m1(1, 2) + m0(2, 2) * m1(2, 2);
 
-	m4(0, 3) = m0(0, 0) * m1(0, 3) + m0(0, 1) * m1(1, 3) +
-		m0(0, 2) * m1(2, 3) + m0(0, 3);
+	m4(0, 3) = m0(0, 0) * m1(0, 3) + m0(0, 1) * m1(1, 3) 
+		+ m0(0, 2) * m1(2, 3) + m0(0, 3);
 
-	m4(1, 3) = m0(1, 0) * m1(0, 3) + m0(1, 1) * m1(1, 3) +
-		m0(1, 2) * m1(2, 3) + m0(1, 3);
+	m4(1, 3) = m0(1, 0) * m1(0, 3) + m0(1, 1) * m1(1, 3) 
+		+ m0(1, 2) * m1(2, 3) + m0(1, 3);
 
-	m4(2, 3) = m0(2, 0) * m1(0, 3) + m0(2, 1) * m1(1, 3) +
-		m0(2, 2) * m1(2, 3) + m0(2, 3);
+	m4(2, 3) = m0(2, 0) * m1(0, 3) + m0(2, 1) * m1(1, 3) 
+		+ m0(2, 2) * m1(2, 3) + m0(2, 3);
 
 	m4(3, 0) = m4(3, 1) = m4(3, 2) = 0.0;
 	m4(3, 3) = 1.0;

+ 2 - 1
anki/math/MathCommonIncludes.h

@@ -1,3 +1,4 @@
 #include "anki/math/Forward.h"
 #include "anki/math/MathSimd.h"
-#include <boost/array.hpp>
+#include <array>
+#include <iosfwd>

+ 1 - 0
anki/math/MathCommonSrc.h

@@ -10,3 +10,4 @@
 #include "anki/math/Math.h"
 #include "anki/util/Assert.h"
 #include <cmath>
+#include <iostream>

+ 1 - 1
anki/math/Transform.h

@@ -19,7 +19,7 @@ public:
 	/// @name Constructors
 	/// @{
 	explicit Transform();
-			 Transform(const Transform& b);
+	Transform(const Transform& b);
 	explicit Transform(const Mat4& m4);
 	explicit Transform(const Vec3& origin, const Mat3& rotation,
 		const float scale);

+ 3 - 3
anki/math/Transform.inl.h

@@ -180,9 +180,9 @@ inline void Transform::invert()
 // Print
 inline std::ostream& operator<<(std::ostream& s, const Transform& a)
 {
-	s << "o: " << a.origin << "\n" <<
-		"s: " << a.scale << "\n" <<
-		"r:\n" << a.rotation;
+	s << "o: " << a.origin << "\n" 
+		<< "s: " << a.scale << "\n" 
+		<< "r:\n" << a.rotation;
 	return s;
 }
 

+ 2 - 2
anki/math/Vec2.h

@@ -20,7 +20,7 @@ public:
 	explicit Vec2(const float x, const float y);
 	explicit Vec2(const float f);
 	explicit Vec2(const float arr[]);
-			 Vec2(const Vec2& b);
+	Vec2(const Vec2& b);
 	explicit Vec2(const Vec3& v3);
 	explicit Vec2(const Vec4& v4);
 	/// @}
@@ -93,7 +93,7 @@ private:
 			float x, y;
 		} vec;
 
-		boost::array<float, 2> arr;
+		std::array<float, 2> arr;
 	};
 	/// @}
 };

+ 2 - 2
anki/math/Vec3.h

@@ -21,7 +21,7 @@ public:
 	explicit Vec3(const float f);
 	explicit Vec3(const float arr[]);
 	explicit Vec3(const Vec2& v2, const float z);
-			 Vec3(const Vec3& b);
+	Vec3(const Vec3& b);
 	explicit Vec3(const Vec4& v4);
 	explicit Vec3(const Quat& q);
 	/// @}
@@ -131,7 +131,7 @@ private:
 			float x, y, z;
 		} vec;
 
-		boost::array<float, 3> arr;
+		std::array<float, 3> arr;
 	};
 	/// @}
 };

+ 12 - 14
anki/math/Vec3.inl.h

@@ -219,18 +219,16 @@ inline Vec3 Vec3::operator-() const
 // ==
 inline bool Vec3::operator==(const Vec3& b) const
 {
-	return Math::isZero(x() - b.x()) &&
-		Math::isZero(y() - b.y()) &&
-		Math::isZero(z() - b.z());
+	return Math::isZero(x() - b.x()) 
+		&& Math::isZero(y() - b.y()) 
+		&& Math::isZero(z() - b.z());
 }
 
 
 // !=
 inline bool Vec3::operator!=(const Vec3& b) const
 {
-	return !(Math::isZero(x() - b.x()) &&
-		Math::isZero(y() - b.y()) &&
-		Math::isZero(z() - b.z()));
+	return !operator==(b);
 }
 
 
@@ -482,12 +480,12 @@ inline Vec3 Vec3::getTransformed(const Mat4& transform) const
 	}
 	return out;
 #else
-	return Vec3(transform(0, 0) * x() + transform(0, 1) * y() +
-		transform(0, 2) * z() + transform(0, 3),
-		transform(1, 0) * x() + transform(1, 1) * y() +
-		transform(1, 2) * z() + transform(1, 3),
-		transform(2, 0) * x() + transform(2, 1) * y() +
-		transform(2, 2) * z() + transform(2, 3)
+	return Vec3(transform(0, 0) * x() + transform(0, 1) * y() 
+		+ transform(0, 2) * z() + transform(0, 3),
+		transform(1, 0) * x() + transform(1, 1) * y() 
+		+ transform(1, 2) * z() + transform(1, 3),
+		transform(2, 0) * x() + transform(2, 1) * y() 
+		+ transform(2, 2) * z() + transform(2, 3)
 	);
 #endif
 }
@@ -503,8 +501,8 @@ inline void Vec3::transform(const Mat4& transform)
 // Transform
 inline Vec3 Vec3::getTransformed(const Transform& transform) const
 {
-	return (transform.getRotation() * ((*this) * transform.getScale())) +
-		transform.getOrigin();
+	return (transform.getRotation() * ((*this) * transform.getScale())) 
+		+ transform.getOrigin();
 }
 
 

+ 2 - 2
anki/math/Vec4.h

@@ -23,7 +23,7 @@ public:
 	explicit Vec4(const float arr[]);
 	explicit Vec4(const Vec2& v2, const float z, const float w);
 	explicit Vec4(const Vec3& v3, const float w);
-			 Vec4(const Vec4& b);
+	Vec4(const Vec4& b);
 	explicit Vec4(const Quat& q);
 #if defined(ANKI_MATH_INTEL_SIMD)
 	explicit Vec4(const __m128& mm);
@@ -112,7 +112,7 @@ private:
 			float x, y, z, w;
 		} vec;
 
-		boost::array<float, 4> arr;
+		std::array<float, 4> arr;
 
 #if defined(ANKI_MATH_INTEL_SIMD)
 		__m128 mm;

+ 6 - 11
anki/math/Vec4.inl.h

@@ -324,21 +324,17 @@ inline Vec4 Vec4::operator-() const
 inline bool Vec4::operator==(const Vec4& b) const
 {
 	Vec4 sub = (*this) - b;
-	return Math::isZero(sub.x()) &&
-		Math::isZero(sub.y()) &&
-		Math::isZero(sub.z()) &&
-		Math::isZero(sub.w());
+	return Math::isZero(sub.x()) 
+		&& Math::isZero(sub.y()) 
+		&& Math::isZero(sub.z()) 
+		&& Math::isZero(sub.w());
 }
 
 
 // !=
 inline bool Vec4::operator!=(const Vec4& b) const
 {
-	Vec4 sub = (*this) - b;
-	return !(Math::isZero(sub.x()) &&
-		Math::isZero(sub.y()) &&
-		Math::isZero(sub.z()) &&
-		Math::isZero(sub.w()));
+	return !operator==(b);
 }
 
 
@@ -417,8 +413,7 @@ inline Vec4 Vec4::operator*(const Mat4& m4) const
 		x() * m4(0, 0) + y() * m4(1, 0) + z() * m4(2, 0) + w() * m4(3, 0),
 		x() * m4(0, 1) + y() * m4(1, 1) + z() * m4(2, 1) + w() * m4(3, 1),
 		x() * m4(0, 2) + y() * m4(1, 2) + z() * m4(2, 2) + w() * m4(3, 2),
-		x() * m4(0, 3) + y() * m4(1, 3) + z() * m4(2, 3) + w() * m4(3, 3)
-	);
+		x() * m4(0, 3) + y() * m4(1, 3) + z() * m4(2, 3) + w() * m4(3, 3));
 }
 
 

+ 30 - 35
anki/renderer/Bl.cpp

@@ -1,18 +1,12 @@
 #include "anki/renderer/Bl.h"
 #include "anki/renderer/RendererInitializer.h"
 #include "anki/renderer/Renderer.h"
-#include "anki/resource/ShaderProgram.h"
+#include "anki/resource/ShaderProgramResource.h"
 
 
 namespace anki {
 
 
-//==============================================================================
-Bl::Bl(Renderer& r_)
-	: SwitchableRenderingPass(r_)
-{}
-
-
 //==============================================================================
 void Bl::init(const RendererInitializer& initializer)
 {
@@ -26,16 +20,16 @@ void Bl::init(const RendererInitializer& initializer)
 	}
 
 	// Horizontal
+	//
 	try
 	{
-		Renderer::createFai(r.getWidth(), r.getHeight(), GL_RGB, GL_RGB,
+		Renderer::createFai(r->getWidth(), r->getHeight(), GL_RGB, GL_RGB,
 			GL_FLOAT, blurFai);
 
 		hBlurFbo.create();
 		hBlurFbo.bind();
-		hBlurFbo.setNumOfColorAttachements(1);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-			GL_TEXTURE_2D, blurFai.getGlId(), 0);
+		std::array<Texture*, 1> fais = {{&blurFai}};
+		hBlurFbo.setColorAttachments(fais);
 	}
 	catch(const std::exception& e)
 	{
@@ -43,17 +37,17 @@ void Bl::init(const RendererInitializer& initializer)
 			"post-processing stage FBO") << e;
 	}
 
-	hBlurSProg.load(ShaderProgram::createSrcCodeToCache(
+	hBlurSProg.load(ShaderProgramResource::createSrcCodeToCache(
 		"shaders/PpsBlurGeneric.glsl", "#define HPASS\n").c_str());
 
 	// Vertical
+	//
 	try
 	{
 		vBlurFbo.create();
 		vBlurFbo.bind();
-		vBlurFbo.setNumOfColorAttachements(1);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-			GL_TEXTURE_2D, r.getPps().getPostPassFai().getGlId(), 0);
+		std::array<const Texture*, 1> fais = {{&r->getPps().getPostPassFai()}};
+		vBlurFbo.setColorAttachments(fais);
 	}
 	catch(std::exception& e)
 	{
@@ -61,17 +55,17 @@ void Bl::init(const RendererInitializer& initializer)
 			"post-processing stage FBO") << e;
 	}
 
-	vBlurSProg.load(ShaderProgram::createSrcCodeToCache(
+	vBlurSProg.load(ShaderProgramResource::createSrcCodeToCache(
 		"shaders/PpsBlurGeneric.glsl", "#define VPASS\n").c_str());
 
 	// Side blur
+	//
 	try
 	{
 		sideBlurFbo.create();
 		sideBlurFbo.bind();
-		sideBlurFbo.setNumOfColorAttachements(1);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-			GL_TEXTURE_2D, r.getMs().getNormalFai().getGlId(), 0);
+		std::array<const Texture*, 1> fais = {{&r->getMs().getNormalFai()}};
+		sideBlurFbo.setColorAttachments(fais);
 	}
 	catch(std::exception& e)
 	{
@@ -98,10 +92,11 @@ void Bl::runSideBlur()
 	glBlendFunc(GL_ONE, GL_ONE);
 
 	sideBlurSProg->bind();
-	sideBlurSProg->findUniformVariableByName("tex").set(*sideBlurMap, 0);
-	sideBlurSProg->findUniformVariableByName("factor").set(sideBlurFactor);
+	sideBlurSProg->findUniformVariableByName("tex")->set(
+		static_cast<const Texture&>(*sideBlurMap));
+	sideBlurSProg->findUniformVariableByName("factor")->set(sideBlurFactor);
 
-	r.drawQuad();
+	r->drawQuad();
 }
 
 
@@ -116,26 +111,26 @@ void Bl::runBlur()
 		hBlurFbo.bind();
 
 		hBlurSProg->bind();
-		hBlurSProg->findUniformVariableByName("img").set(
-			r.getPps().getPostPassFai(), 0);
-		hBlurSProg->findUniformVariableByName("msNormalFai").set(
-			r.getMs().getNormalFai(), 1);
-		float tmp = r.getWidth();
-		hBlurSProg->findUniformVariableByName("imgDimension").set(tmp);
+		hBlurSProg->findUniformVariableByName("img")->set(
+			r->getPps().getPostPassFai());
+		hBlurSProg->findUniformVariableByName("msNormalFai")->set(
+			r->getMs().getNormalFai());
+		hBlurSProg->findUniformVariableByName("imgDimension")->set(
+			float(r->getWidth()));
 
-		r.drawQuad();
+		r->drawQuad();
 
 		// vpass
 		vBlurFbo.bind();
 
 		vBlurSProg->bind();
-		vBlurSProg->findUniformVariableByName("img").set(blurFai, 0);
-		vBlurSProg->findUniformVariableByName("msNormalFai").set(
-			r.getMs().getNormalFai(), 1);
-		tmp = r.getHeight();
-		vBlurSProg->findUniformVariableByName("imgDimension").set(tmp);
+		vBlurSProg->findUniformVariableByName("img")->set(blurFai);
+		vBlurSProg->findUniformVariableByName("msNormalFai")->set(
+			r->getMs().getNormalFai());
+		vBlurSProg->findUniformVariableByName("imgDimension")->set(
+			float(r->getHeight()));
 
-		r.drawQuad();
+		r->drawQuad();
 	}
 }
 

+ 7 - 4
anki/renderer/Bl.h

@@ -2,7 +2,7 @@
 #define ANKI_RENDERER_BL_H
 
 #include "anki/renderer/RenderingPass.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include "anki/resource/Resource.h"
 #include "anki/gl/Fbo.h"
 
@@ -10,14 +10,17 @@
 namespace anki {
 
 
-class ShaderProgram;
+class ShaderProgramResource;
 
 
 /// Blurring rendering pass
 class Bl: public SwitchableRenderingPass
 {
 public:
-	Bl(Renderer& r_);
+	Bl(Renderer* r)
+		: SwitchableRenderingPass(r)
+	{}
+
 	void init(const RendererInitializer& initializer);
 	void run();
 
@@ -62,7 +65,7 @@ private:
 	Texture blurFai; ///< Temp FAI for blurring
 	TextureResourcePointer sideBlurMap;
 
-	uint blurringIterationsNum;
+	uint blurringIterationsNum; ///< How many times the pass will run
 	float sideBlurFactor;
 
 	void runBlur();

+ 3 - 5
anki/renderer/Bs.cpp

@@ -12,15 +12,11 @@
 namespace anki {
 
 
-//==============================================================================
-// Destructor                                                                  =
 //==============================================================================
 Bs::~Bs()
 {}
 
 
-//==============================================================================
-// createFbo                                                                   =
 //==============================================================================
 void Bs::createFbo()
 {
@@ -28,6 +24,8 @@ void Bs::createFbo()
 	{
 		fbo.create();
 		fbo.bind();
+	
+		std::array<>
 
 		fbo.setNumOfColorAttachements(1);
 
@@ -42,7 +40,7 @@ void Bs::createFbo()
 	}
 	catch(std::exception& e)
 	{
-		throw ANKI_EXCEPTION("Failed to create blending stage FBO");
+		throw ANKI_EXCEPTION("Failed to create blending stage FBO") << e;
 	}
 }
 

+ 16 - 13
anki/renderer/Bs.h

@@ -4,7 +4,7 @@
 #include "anki/renderer/RenderingPass.h"
 #include "anki/gl/Fbo.h"
 #include "anki/resource/Resource.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 
 
 namespace anki {
@@ -17,21 +17,24 @@ class ShaderProgram;
 /// The objects that blend must be handled differently
 class Bs: public RenderingPass
 {
-	public:
-		Bs(Renderer& r_): RenderingPass(r_) {}
-		~Bs();
+public:
+	Bs(Renderer* r)
+		: RenderingPass(r) 
+	{}
 
-		void init(const RendererInitializer& initializer);
-		void run();
+	~Bs();
 
-	private:
-		Fbo fbo; ///< Writes to Pps::prePassFai
-		Fbo refractFbo; ///< Writes to refractFai
-		ShaderProgramResourcePointer refractSProg;
-		Texture refractFai;
+	void init(const RendererInitializer& initializer);
+	void run();
 
-		void createFbo();
-		void createRefractFbo();
+private:
+	Fbo fbo; ///< Writes to Pps::prePassFai
+	Fbo refractFbo; ///< Writes to refractFai
+	ShaderProgramResourcePointer refractSProg;
+	Texture refractFai;
+
+	void createFbo();
+	void createRefractFbo();
 };
 
 

+ 2 - 2
anki/renderer/Ez.h

@@ -12,8 +12,8 @@ namespace anki {
 class Ez: public SwitchableRenderingPass
 {
 	public:
-		Ez(Renderer& r_)
-			: SwitchableRenderingPass(r_)
+		Ez(Renderer* r)
+			: SwitchableRenderingPass(r)
 		{}
 
 		void init(const RendererInitializer& initializer);

+ 1 - 1
anki/renderer/Hdr.h

@@ -3,7 +3,7 @@
 
 #include "anki/renderer/RenderingPass.h"
 #include "anki/gl/Fbo.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include "anki/resource/Resource.h"
 
 

+ 2 - 2
anki/renderer/Is.h

@@ -3,9 +3,9 @@
 
 #include "anki/renderer/RenderingPass.h"
 #include "anki/gl/Fbo.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include "anki/resource/Resource.h"
-#include "anki/resource/ShaderProgram.h"
+#include "anki/resource/ShaderProgramResource.h"
 #include "anki/math/Math.h"
 #include "anki/gl/Vbo.h"
 #include "anki/gl/Vao.h"

+ 1 - 1
anki/renderer/Ms.h

@@ -2,7 +2,7 @@
 #define ANKI_RENDERER_MS_H
 
 #include "anki/renderer/RenderingPass.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include "anki/gl/Fbo.h"
 #include "anki/renderer/Ez.h"
 

+ 1 - 1
anki/renderer/Pps.h

@@ -3,7 +3,7 @@
 
 #include "anki/renderer/RenderingPass.h"
 #include "anki/gl/Fbo.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include "anki/resource/Resource.h"
 #include "anki/renderer/Hdr.h"
 #include "anki/renderer/Ssao.h"

+ 2 - 2
anki/renderer/Renderer.h

@@ -3,8 +3,8 @@
 
 #include "anki/math/Math.h"
 #include "anki/gl/Fbo.h"
-#include "anki/resource/Texture.h"
-#include "anki/resource/ShaderProgram.h"
+#include "anki/resource/TextureResource.h"
+#include "anki/resource/ShaderProgramResource.h"
 #include "anki/gl/Vbo.h"
 #include "anki/gl/Vao.h"
 #include "anki/resource/Resource.h"

+ 3 - 3
anki/renderer/RenderingPass.h

@@ -13,7 +13,7 @@ struct RendererInitializer;
 class RenderingPass
 {
 public:
-	RenderingPass(Renderer& r_)
+	RenderingPass(Renderer* r_)
 		: r(r_)
 	{}
 
@@ -24,7 +24,7 @@ public:
 	virtual void init(const RendererInitializer& initializer) = 0;
 
 protected:
-	Renderer& r; ///< Know your father
+	Renderer* r; ///< Know your father
 };
 
 
@@ -32,7 +32,7 @@ protected:
 class SwitchableRenderingPass: public RenderingPass
 {
 public:
-	SwitchableRenderingPass(Renderer& r_)
+	SwitchableRenderingPass(Renderer* r_)
 		: RenderingPass(r_)
 	{}
 

+ 4 - 4
anki/renderer/Sm.h

@@ -3,7 +3,7 @@
 
 #include "anki/renderer/RenderingPass.h"
 #include "anki/gl/Fbo.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include "anki/scene/VisibilityTester.h"
 
 
@@ -17,8 +17,8 @@ class Light;
 class Sm: private RenderingPass
 {
 	public:
-		Sm(Renderer& r_)
-		:	RenderingPass(r_)
+		Sm(Renderer* r_)
+			: RenderingPass(r_)
 		{}
 
 		/// @name Accessors
@@ -75,7 +75,7 @@ class Sm: private RenderingPass
 			float distance;
 		};
 
-		boost::array<Level, 4> levels; ///< The levels of detail. The 0 is the
+		std::array<Level, 4> levels; ///< The levels of detail. The 0 is the
 		                               ///< detailed one
 		Level* crntLevel; ///< Current level of detail. Assigned by run
 

+ 1 - 1
anki/renderer/Smo.h

@@ -14,7 +14,7 @@ class Light;
 class Smo: public RenderingPass
 {
 public:
-	Smo(Renderer& r_)
+	Smo(Renderer* r_)
 		: RenderingPass(r_)
 	{}
 

+ 4 - 4
anki/renderer/Ssao.h

@@ -3,8 +3,8 @@
 
 #include "anki/renderer/RenderingPass.h"
 #include "anki/gl/Fbo.h"
-#include "anki/resource/Texture.h"
-#include "anki/resource/ShaderProgram.h"
+#include "anki/resource/TextureResource.h"
+#include "anki/resource/ShaderProgramResource.h"
 #include "anki/resource/Resource.h"
 #include "anki/gl/Vbo.h"
 #include "anki/gl/Vao.h"
@@ -22,8 +22,8 @@ namespace anki {
 class Ssao: public SwitchableRenderingPass
 {
 	public:
-		Ssao(Renderer& r_)
-		:	SwitchableRenderingPass(r_)
+		Ssao(Renderer* r_)
+			: SwitchableRenderingPass(r_)
 		{}
 
 		void init(const RendererInitializer& initializer);

+ 1 - 1
anki/resource/LightRsrc.cpp

@@ -1,5 +1,5 @@
 #include "anki/resource/LightRsrc.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include "anki/misc/PropertyTree.h"
 #include "anki/core/Logger.h"
 #include "anki/core/Globals.h"

+ 1 - 1
anki/resource/LightRsrc.h

@@ -3,7 +3,7 @@
 
 #include "anki/math/Math.h"
 #include "anki/resource/Resource.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 
 
 namespace anki {

+ 13 - 14
anki/resource/Material.cpp

@@ -3,8 +3,8 @@
 #include "anki/resource/MaterialShaderProgramCreator.h"
 #include "anki/core/App.h"
 #include "anki/core/Globals.h"
-#include "anki/resource/ShaderProgram.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/ShaderProgramResource.h"
+#include "anki/resource/TextureResource.h"
 #include <boost/foreach.hpp>
 #include <boost/property_tree/ptree.hpp>
 #include <boost/property_tree/xml_parser.hpp>
@@ -55,26 +55,25 @@ void MaterialVariable::init(const char* shaderProgVarName,
 		const PassLevelKey& key = it->first;
 
 		// Variable exists
-		if(sProg.uniformVariableExists(shaderProgVarName))
+		const ShaderProgramUniformVariable* uni = 
+			sProg.findUniformVariableByName(shaderProgVarName);
+		if(uni)
 		{
-			const ShaderProgramUniformVariable& sProgVar =
-				sProg.findUniformVariableByName(shaderProgVarName);
-
-			sProgVars[key] = &sProgVar;
+			sProgVars[key] = uni;
 
 			// Set oneSProgVar
 			if(!oneSProgVar)
 			{
-				oneSProgVar = &sProgVar;
+				oneSProgVar = uni;
 			}
 
 			// Sanity check: All the sprog vars need to have same GL data type
-			if(oneSProgVar->getGlDataType() != sProgVar.getGlDataType() ||
-				oneSProgVar->getType() != sProgVar.getType())
+			if(oneSProgVar->getGlDataType() != uni->getGlDataType() 
+				|| oneSProgVar->getType() != uni->getType())
 			{
 				throw ANKI_EXCEPTION("Incompatible shader "
-					"program variables: " +
-					shaderProgVarName);
+					"program variables: " 
+					+ shaderProgVarName);
 			}
 		}
 	}
@@ -83,8 +82,8 @@ void MaterialVariable::init(const char* shaderProgVarName,
 	if(!oneSProgVar)
 	{
 		throw ANKI_EXCEPTION("Variable not found in "
-			"any of the shader programs: " +
-			shaderProgVarName);
+			"any of the shader programs: " 
+			+ shaderProgVarName);
 	}
 }
 

+ 5 - 5
anki/resource/Model.cpp

@@ -4,7 +4,7 @@
 #include "anki/resource/SkelAnim.h"
 #include "anki/resource/MeshLoader.h"
 #include "anki/resource/Skeleton.h"
-#include "anki/resource/ShaderProgram.h"
+#include "anki/resource/ShaderProgramResource.h"
 #include <boost/foreach.hpp>
 #include <boost/property_tree/ptree.hpp>
 #include <boost/property_tree/xml_parser.hpp>
@@ -27,7 +27,7 @@ Vao* ModelPatchBase::createNewVao(const Material& mtl,
 	Vao* vao = new Vao;
 	vao->create();
 
-	if(mtl.getShaderProgram(key).attributeVariableExists("position"))
+	if(mtl.getShaderProgram(key).findAttributeVariableByName("position"))
 	{
 		const Vbo* vbo = meshb.getVbo(Mesh::VBO_POSITIONS);
 		ANKI_ASSERT(vbo != NULL);
@@ -35,7 +35,7 @@ Vao* ModelPatchBase::createNewVao(const Material& mtl,
 		vao->attachArrayBufferVbo(*vbo, 0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 	}
 
-	if(mtl.getShaderProgram(key).attributeVariableExists("normal"))
+	if(mtl.getShaderProgram(key).findAttributeVariableByName("normal"))
 	{
 		const Vbo* vbo = meshb.getVbo(Mesh::VBO_NORMALS);
 		ANKI_ASSERT(vbo != NULL);
@@ -43,7 +43,7 @@ Vao* ModelPatchBase::createNewVao(const Material& mtl,
 		vao->attachArrayBufferVbo(*vbo, 1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 	}
 
-	if(mtl.getShaderProgram(key).attributeVariableExists("tangent"))
+	if(mtl.getShaderProgram(key).findAttributeVariableByName("tangent"))
 	{
 		const Vbo* vbo = meshb.getVbo(Mesh::VBO_TANGENTS);
 		ANKI_ASSERT(vbo != NULL);
@@ -51,7 +51,7 @@ Vao* ModelPatchBase::createNewVao(const Material& mtl,
 		vao->attachArrayBufferVbo(*vbo, 2, 4, GL_FLOAT, GL_FALSE, 0, NULL);
 	}
 
-	if(mtl.getShaderProgram(key).attributeVariableExists("texCoords"))
+	if(mtl.getShaderProgram(key).findAttributeVariableByName("texCoords"))
 	{
 		const Vbo* vbo = meshb.getVbo(Mesh::VBO_TEX_COORDS);
 		ANKI_ASSERT(vbo != NULL);

+ 20 - 20
anki/resource/Resource.h

@@ -9,26 +9,26 @@
 namespace anki {
 
 
-#define ANKI_RESOURCE_TYPEDEFS(x) \
-	class x; \
-	typedef ResourceManager<x> x ## ResourceManager; \
-	typedef Singleton<x ## ResourceManager> x ## ResourceManagerSingleton; \
-	typedef ResourcePointer<x, x ## ResourceManagerSingleton> \
-		x ## ResourcePointer;
-
-
-ANKI_RESOURCE_TYPEDEFS(Texture)
-ANKI_RESOURCE_TYPEDEFS(ShaderProgram)
-ANKI_RESOURCE_TYPEDEFS(Material)
-ANKI_RESOURCE_TYPEDEFS(Mesh)
-ANKI_RESOURCE_TYPEDEFS(Skeleton)
-ANKI_RESOURCE_TYPEDEFS(SkelAnim)
-ANKI_RESOURCE_TYPEDEFS(LightRsrc)
-ANKI_RESOURCE_TYPEDEFS(ParticleEmitterRsrc)
-ANKI_RESOURCE_TYPEDEFS(Script)
-ANKI_RESOURCE_TYPEDEFS(Model)
-ANKI_RESOURCE_TYPEDEFS(Skin)
-ANKI_RESOURCE_TYPEDEFS(DummyRsrc)
+#define ANKI_RESOURCE_TYPEDEFS(rsrc, name) \
+	class rsrc; \
+	typedef ResourceManager<rsrc> rsrc ## ResourceManager; \
+	typedef Singleton<rsrc ## ResourceManager> \
+		rsrc ## ResourceManagerSingleton; \
+	typedef ResourcePointer<rsrc, rsrc ## ResourceManagerSingleton> name;
+
+
+ANKI_RESOURCE_TYPEDEFS(TextureResource, TextureResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(ShaderProgramResource, ShaderProgramResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(Material, MaterialResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(Mesh, MeshResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(Skeleton, SkeletonResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(SkelAnim, SkelAnimResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(LightRsrc, LightRsrcResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(ParticleEmitterRsrc, ParticleEmitterRsrcResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(Script, ScriptResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(Model, ModelResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(Skin, SkinResourcePointer)
+ANKI_RESOURCE_TYPEDEFS(DummyRsrc, DummyRsrcResourcePointer)
 
 
 } // end namespace

+ 80 - 0
anki/resource/ShaderProgramResource.cpp

@@ -0,0 +1,80 @@
+#include "anki/resource/ShaderProgramResource.h"
+#include "anki/resource/ShaderProgramPrePreprocessor.h"
+#include "anki/core/App.h" // To get cache dir
+#include "anki/util/Util.h"
+#include "anki/util/Exception.h"
+#include <boost/filesystem.hpp>
+#include <fstream>
+#include <sstream>
+
+
+namespace anki {
+
+
+//==============================================================================
+void ShaderProgramResource::load(const char* filename)
+{
+	ShaderProgramPrePreprocessor pars(filename);
+
+	boost::array<const char*, 128> trfVarsArr = {{nullptr}};
+	if(pars.getTranformFeedbackVaryings().size() > 0)
+	{
+		uint i;
+		for(i = 0; i < pars.getTranformFeedbackVaryings().size(); i++)
+		{
+			trfVarsArr[i] = pars.getTranformFeedbackVaryings()[i].c_str();
+		}
+		trfVarsArr[i] = nullptr;
+	}
+
+	create(pars.getShaderSource(ST_VERTEX).c_str(), 
+		nullptr, 
+		nullptr, 
+		nullptr, 
+		pars.getShaderSource(ST_FRAGMENT).c_str(),
+		&trfVarsArr[0]);
+}
+
+
+//==============================================================================
+std::string ShaderProgramResource::createSrcCodeToCache(
+	const char* sProgFPathName, const char* preAppendedSrcCode)
+{
+	using namespace boost::filesystem;
+
+	if(strlen(preAppendedSrcCode) < 1)
+	{
+		return sProgFPathName;
+	}
+
+	// Create suffix
+	boost::hash<std::string> stringHash;
+	std::size_t h = stringHash(preAppendedSrcCode);
+	std::string suffix = boost::lexical_cast<std::string>(h);
+
+	//
+	path newfPathName = AppSingleton::get().getCachePath() 
+		/ (path(sProgFPathName).filename().string() + "." + suffix);
+
+	if(exists(newfPathName))
+	{
+		return newfPathName.string();
+	}
+
+	std::string src_ = Util::readFile(sProgFPathName);
+	std::string src = preAppendedSrcCode + src_;
+
+	std::ofstream f(newfPathName.string().c_str());
+	if(!f.is_open())
+	{
+		throw ANKI_EXCEPTION("Cannot open file for writing \"" 
+			+ newfPathName.string() + "\"");
+	}
+
+	f.write(src.c_str(), src.length());
+
+	return newfPathName.string();
+}
+
+
+} // end namespace

+ 32 - 0
anki/resource/ShaderProgramResource.h

@@ -0,0 +1,32 @@
+#ifndef ANKI_RESOURCE_SHADER_PROGRAM_RESOURCE_H
+#define ANKI_RESOURCE_SHADER_PROGRAM_RESOURCE_H
+
+#include "anki/gl/ShaderProgram.h"
+
+
+namespace anki {
+
+
+/// Shader program resource
+class ShaderProgramResource: public ShaderProgram
+{
+public:
+	/// Resource load
+	void load(const char* filename);
+
+	/// Used by @ref Material and @ref Renderer to create custom shaders in
+	/// the cache
+	/// @param sProgFPathName The file pathname of the shader prog
+	/// @param preAppendedSrcCode The source code we want to write on top
+	///        of the shader prog
+	/// @return The file pathname of the new shader prog. Its
+	///         $HOME/.anki/cache/newFNamePrefix_fName
+	static std::string createSrcCodeToCache(const char* sProgFPathName,
+		const char* preAppendedSrcCode);
+}; 
+
+
+} // end namespace
+
+
+#endif

+ 2 - 1
anki/resource/Skeleton.h

@@ -3,6 +3,7 @@
 
 #include "anki/math/Math.h"
 #include <vector>
+#include <array>
 
 
 namespace anki {
@@ -87,7 +88,7 @@ private:
 	uint id; ///< Pos inside the @ref Skeleton::bones vector
 	static const uint MAX_CHILDS_PER_BONE = 4; ///< Please dont change this
 	Bone* parent;
-	boost::array<Bone*, MAX_CHILDS_PER_BONE> childs;
+	std::array<Bone*, MAX_CHILDS_PER_BONE> childs;
 	ushort childsNum;
 
 	// see the class notes

+ 0 - 390
anki/resource/Texture.cpp

@@ -1,390 +0,0 @@
-#include "anki/resource/Texture.h"
-#include "anki/resource/Image.h"
-#include "anki/gl/GlException.h"
-#include "anki/util/Exception.h"
-
-#include <GL/glew.h>
-#include <boost/lexical_cast.hpp>
-
-
-namespace anki {
-
-
-#define LAST_TEX_UNIT (textureUnitsNum - 1)
-
-
-//==============================================================================
-// Statics                                                                     =
-//==============================================================================
-int Texture::textureUnitsNum = -1;
-bool Texture::mipmappingEnabled = true;
-bool Texture::compressionEnabled = false;
-int Texture::anisotropyLevel = 8;
-
-
-//==============================================================================
-// Constructor                                                                 =
-//==============================================================================
-Texture::Texture():
-	glId(std::numeric_limits<uint>::max()),
-	target(GL_TEXTURE_2D)
-{}
-
-
-//==============================================================================
-// Destructor                                                                  =
-//==============================================================================
-Texture::~Texture()
-{
-	if(isLoaded())
-	{
-		glDeleteTextures(1, &glId);
-	}
-}
-
-
-//==============================================================================
-// load (const char*)                                                          =
-//==============================================================================
-void Texture::load(const char* filename)
-{
-	try
-	{
-		load(Image(filename));
-	}
-	catch(std::exception& e)
-	{
-		throw ANKI_EXCEPTION("File \"" + filename + "\"") << e;
-	}
-}
-
-
-//==============================================================================
-// load (const Image&)                                                         =
-//==============================================================================
-void Texture::load(const Image& img)
-{
-	Initializer init;
-	init.width = img.getWidth();
-	init.height = img.getHeight();
-	init.dataSize = img.getDataSize();
-
-	switch(img.getColorType())
-	{
-		case Image::CT_R:
-			init.internalFormat = (compressionEnabled) ?
-				GL_COMPRESSED_RED : GL_RED;
-			init.format = GL_RED;
-			init.type = GL_UNSIGNED_BYTE;
-			break;
-
-		case Image::CT_RGB:
-			init.internalFormat = (compressionEnabled) ?
-				GL_COMPRESSED_RGB : GL_RGB;
-			init.format = GL_RGB;
-			init.type = GL_UNSIGNED_BYTE;
-			break;
-
-		case Image::CT_RGBA:
-			init.internalFormat = (compressionEnabled) ?
-				GL_COMPRESSED_RGBA : GL_RGBA;
-			init.format = GL_RGBA;
-			init.type = GL_UNSIGNED_BYTE;
-			break;
-
-		default:
-			throw ANKI_EXCEPTION("See file: " +
-				boost::lexical_cast<std::string>(img.getColorType()));
-	}
-
-	switch(img.getDataCompression())
-	{
-		case Image::DC_NONE:
-			init.dataCompression = DC_NONE;
-			break;
-
-		case Image::DC_DXT1:
-			init.dataCompression = DC_DXT1;
-			init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-			break;
-
-		case Image::DC_DXT3:
-			init.dataCompression = DC_DXT3;
-			init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
-			break;
-
-		case Image::DC_DXT5:
-			init.dataCompression = DC_DXT5;
-			init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
-			break;
-	}
-
-	init.data = img.getData();
-	init.mipmapping = mipmappingEnabled;
-	init.filteringType = mipmappingEnabled ? TFT_TRILINEAR : TFT_LINEAR;
-	init.repeat = true;
-	init.anisotropyLevel = anisotropyLevel;
-
-	create(init);
-}
-
-
-//==============================================================================
-// create                                                                      =
-//==============================================================================
-void Texture::create(const Initializer& init_)
-{
-	Initializer init = init_;
-
-	//
-	// Sanity checks
-	//
-	if(isLoaded())
-	{
-		throw ANKI_EXCEPTION("Already loaded");
-	}
-
-	if(init.internalFormat <= 4)
-	{
-		throw ANKI_EXCEPTION("Deprecated internal format");
-	}
-
-	//
-	// Create
-	//
-	glGenTextures(1, &glId);
-	bind(LAST_TEX_UNIT);
-	target = GL_TEXTURE_2D;
-	internalFormat = init.internalFormat;
-	format = init.format;
-	type = init.type;
-
-	if(init.data == NULL)
-	{
-		init.dataCompression = DC_NONE;
-	}
-
-	switch(init.dataCompression)
-	{
-		case DC_NONE:
-			glTexImage2D(target, 0, init.internalFormat, init.width,
-				init.height, 0, init.format, init.type, init.data);
-			break;
-
-		case DC_DXT1:
-		case DC_DXT3:
-		case DC_DXT5:
-			glCompressedTexImage2D(target, 0, init.internalFormat,
-				init.width, init.height, 0, init.dataSize, init.data);
-			break;
-
-		default:
-			throw ANKI_EXCEPTION("Incorrect data compression value");
-	}
-
-	setRepeat(init.repeat);
-
-	if(init.mipmapping)
-	{
-		glGenerateMipmap(target);
-	}
-
-	// If not mipmapping then the filtering cannot be trilinear
-	if(init.filteringType == TFT_TRILINEAR && !init.mipmapping)
-	{
-		setFiltering(TFT_LINEAR);
-	}
-	else
-	{
-		setFiltering(init.filteringType);
-	}
-
-	if(init.anisotropyLevel > 1)
-	{
-		setTexParameter(GL_TEXTURE_MAX_ANISOTROPY_EXT,
-			float(init.anisotropyLevel));
-	}
-
-	ANKI_CHECK_GL_ERROR();
-}
-
-
-//==============================================================================
-// bind                                                                        =
-//==============================================================================
-void Texture::bind(uint unit) const
-{
-	if(unit >= static_cast<uint>(textureUnitsNum))
-	{
-		throw ANKI_EXCEPTION("Max tex units passed");
-	}
-
-	glActiveTexture(GL_TEXTURE0 + unit);
-	glBindTexture(target, getGlId());
-}
-
-
-//==============================================================================
-// getWidth                                                                    =
-//==============================================================================
-int Texture::getWidth(uint level) const
-{
-	bind(LAST_TEX_UNIT);
-	int i;
-	glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &i);
-	return i;
-}
-
-
-//==============================================================================
-// getHeight                                                                   =
-//==============================================================================
-int Texture::getHeight(uint level) const
-{
-	bind(LAST_TEX_UNIT);
-	int i;
-	glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &i);
-	return i;
-}
-
-
-//==============================================================================
-// setTexParameter [int]                                                       =
-//==============================================================================
-void Texture::setTexParameter(uint paramName, int value) const
-{
-	bind(LAST_TEX_UNIT);
-	glTexParameteri(target, paramName, value);
-}
-
-
-//==============================================================================
-// setTexParameter [float]                                                     =
-//==============================================================================
-void Texture::setTexParameter(uint paramName, float value) const
-{
-	bind(LAST_TEX_UNIT);
-	glTexParameterf(target, paramName, value);
-}
-
-
-//==============================================================================
-// setRepeat                                                                   =
-//==============================================================================
-void Texture::setRepeat(bool repeat) const
-{
-	bind(LAST_TEX_UNIT);
-	if(repeat)
-	{
-		setTexParameter(GL_TEXTURE_WRAP_S, GL_REPEAT);
-		setTexParameter(GL_TEXTURE_WRAP_T, GL_REPEAT);
-	}
-	else
-	{
-		setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-	}
-}
-
-
-//==============================================================================
-// getBaseLevel                                                                =
-//==============================================================================
-int Texture::getBaseLevel() const
-{
-	bind(LAST_TEX_UNIT);
-	int level;
-	glGetTexParameteriv(target, GL_TEXTURE_BASE_LEVEL, &level);
-	return level;
-}
-
-
-//==============================================================================
-// getActiveTexUnit                                                            =
-//==============================================================================
-uint Texture::getActiveTexUnit()
-{
-	int unit;
-	glGetIntegerv(GL_ACTIVE_TEXTURE, &unit);
-	return unit - GL_TEXTURE0;
-}
-
-
-//==============================================================================
-// getBindedTexId                                                              =
-//==============================================================================
-uint Texture::getBindedTexId(uint unit)
-{
-	int id;
-	glActiveTexture(GL_TEXTURE0 + unit);
-	glGetIntegerv(GL_TEXTURE_BINDING_2D, &id);
-	return id;
-}
-
-
-//==============================================================================
-// getMaxLevel                                                                 =
-//==============================================================================
-int Texture::getMaxLevel() const
-{
-	bind(LAST_TEX_UNIT);
-	int level;
-	glGetTexParameteriv(target, GL_TEXTURE_MAX_LEVEL, &level);
-	return level;
-}
-
-
-//==============================================================================
-// setAnisotropy                                                               =
-//==============================================================================
-void Texture::setAnisotropy(uint level)
-{
-	bind(LAST_TEX_UNIT);
-	setTexParameter(GL_TEXTURE_MAX_ANISOTROPY_EXT, int(level));
-}
-
-
-//==============================================================================
-// setMipmapLevel                                                              =
-//==============================================================================
-void Texture::setMipmapLevel(uint level)
-{
-	bind(LAST_TEX_UNIT);
-	setTexParameter(GL_TEXTURE_BASE_LEVEL, int(level));
-}
-
-
-//==============================================================================
-// genMipmap                                                                   =
-//==============================================================================
-void Texture::genMipmap()
-{
-	bind(LAST_TEX_UNIT);
-	glGenerateMipmap(target);
-}
-
-
-//==============================================================================
-// setFiltering                                                                =
-//==============================================================================
-void Texture::setFiltering(TextureFilteringType filterType)
-{
-	switch(filterType)
-	{
-		case TFT_NEAREST:
-			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-			break;
-		case TFT_LINEAR:
-			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-			break;
-		case TFT_TRILINEAR:
-			glTexParameteri(target, GL_TEXTURE_MIN_FILTER,
-				GL_LINEAR_MIPMAP_LINEAR);
-			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	}
-}
-
-
-} // end namespace

+ 0 - 153
anki/resource/Texture.h

@@ -1,153 +0,0 @@
-#ifndef ANKI_RESOURCE_TEXTURE_H
-#define ANKI_RESOURCE_TEXTURE_H
-
-#include "anki/util/StdTypes.h"
-#include "anki/util/Assert.h"
-#include <cstdlib>
-#include <limits>
-
-
-namespace anki {
-
-
-class Image;
-
-
-/// Texture resource class
-///
-/// It loads or creates an image and then loads it in the GPU. Its an OpenGL
-/// container. It supports compressed and uncompressed TGAs and some of the
-/// formats of PNG (PNG loading uses libpng)
-///
-/// @note The last texture unit is reserved and you cannot use it
-class Texture
-{
-public:
-	enum TextureFilteringType
-	{
-		TFT_NEAREST,
-		TFT_LINEAR,
-		TFT_TRILINEAR
-	};
-
-	enum DataCompression
-	{
-		DC_NONE,
-		DC_DXT1,
-		DC_DXT3,
-		DC_DXT5
-	};
-
-	/// Texture initializer struct
-	struct Initializer
-	{
-		float width;
-		float height;
-		int internalFormat;
-		int format;
-		uint type;
-		const void* data;
-		bool mipmapping;
-		TextureFilteringType filteringType;
-		bool repeat;
-		int anisotropyLevel;
-		DataCompression dataCompression;
-		size_t dataSize; ///< For compressed textures
-	};
-
-	/// Default constructor
-	Texture();
-
-	/// Desrcuctor
-	~Texture();
-
-
-	/// @name Accessors
-	/// @{
-	uint getGlId() const
-	{
-		ANKI_ASSERT(isLoaded());
-		return glId;
-	}
-
-	uint getInternalFormat() const
-	{
-		ANKI_ASSERT(isLoaded());
-		return internalFormat;
-	}
-
-	uint getFormat() const
-	{
-		ANKI_ASSERT(isLoaded());
-		return format;
-	}
-
-	uint getType() const
-	{
-		ANKI_ASSERT(isLoaded());
-		return type;
-	}
-
-	static int& getTextureUnitsNum()
-	{
-		return textureUnitsNum;
-	}
-	/// @}
-
-	/// @name Create tex funcs
-	/// @{
-
-	/// Implements Resource::load
-	/// @exception Exception
-	void load(const char* filename);
-
-	/// @exception Exception
-	void load(const Image& img);
-
-	/// Create a texture
-	void create(const Initializer& init);
-	/// @}
-
-	void bind(uint texUnit = 0) const;
-	void setRepeat(bool repeat) const;
-	void setFiltering(TextureFilteringType filterType);
-	void setAnisotropy(uint level);
-	void setMipmapLevel(uint level);
-	void genMipmap();
-	int getWidth(uint level = 0) const;
-	int getHeight(uint level = 0) const;
-	int getBaseLevel() const;
-	int getMaxLevel() const;
-	static uint getActiveTexUnit();
-	static uint getBindedTexId(uint unit);
-
-private:
-	uint glId; ///< Identification for OGL
-	uint target; ///< GL_TEXTURE_2D, GL_TEXTURE_3D... etc
-	uint internalFormat; ///< GL_COMPRESSED_RED, GL_RGB16 etc
-	uint format; ///< GL_RED, GL_RG, GL_RGB etc
-	uint type; ///< GL_UNSIGNED_BYTE, GL_BYTE etc
-
-	/// @name Variables set by the renderer
-	/// Set upon OpenGL initialization
-	/// @{
-	static int  textureUnitsNum;
-	static bool mipmappingEnabled;
-	static bool compressionEnabled;
-	static int  anisotropyLevel;
-	/// @}
-
-	void setTexParameter(uint paramName, int value) const;
-	void setTexParameter(uint paramName, float value) const;
-
-	bool isLoaded() const
-	{
-		return glId != std::numeric_limits<uint>::max();
-	}
-};
-
-
-} // end namespace
-
-
-#endif

+ 89 - 0
anki/resource/TextureResource.cpp

@@ -0,0 +1,89 @@
+#include "anki/resource/TextureResource.h"
+#include "anki/resource/Image.h"
+#include "anki/util/Exception.h"
+
+
+namespace anki {
+
+
+//==============================================================================
+void TextureResource::load(const char* filename)
+{
+	try
+	{
+		load(Image(filename));
+	}
+	catch(std::exception& e)
+	{
+		throw ANKI_EXCEPTION("File \"" + filename + "\"") << e;
+	}
+}
+
+
+//==============================================================================
+void TextureResource::load(const Image& img)
+{
+	Initializer init;
+	init.width = img.getWidth();
+	init.height = img.getHeight();
+	init.dataSize = img.getDataSize();
+
+	bool compressionEnabled = 
+		TextureManagerSingleton::get().getCompressionEnabled();
+
+	switch(img.getColorType())
+	{
+	case Image::CT_R:
+		init.internalFormat = (compressionEnabled) 
+			? GL_COMPRESSED_RED : GL_RED;
+		init.format = GL_RED;
+		init.type = GL_UNSIGNED_BYTE;
+		break;
+
+	case Image::CT_RGB:
+		init.internalFormat = (compressionEnabled) 
+			? GL_COMPRESSED_RGB : GL_RGB;
+		init.format = GL_RGB;
+		init.type = GL_UNSIGNED_BYTE;
+		break;
+
+	case Image::CT_RGBA:
+		init.internalFormat = (compressionEnabled) 
+			? GL_COMPRESSED_RGBA : GL_RGBA;
+		init.format = GL_RGBA;
+		init.type = GL_UNSIGNED_BYTE;
+		break;
+
+	default:
+		ANKI_ASSERT(0);
+	}
+
+	switch(img.getDataCompression())
+	{
+	case Image::DC_NONE:
+		break;
+
+	case Image::DC_DXT1:
+		init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+		break;
+
+	case Image::DC_DXT3:
+		init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+		break;
+
+	case Image::DC_DXT5:
+		init.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+		break;
+	}
+
+	init.data = img.getData();
+	init.mipmapping = TextureManagerSingleton::get().getMipmappingEnabled();
+	init.filteringType = init.mipmapping ? TFT_TRILINEAR : TFT_LINEAR;
+	init.repeat = true;
+	init.anisotropyLevel = TextureManagerSingleton::get().getAnisotropyLevel();
+
+	create(init);
+}
+
+
+} // end namespace

+ 32 - 0
anki/resource/TextureResource.h

@@ -0,0 +1,32 @@
+#ifndef ANKI_RESOURCE_TEXTURE_RESOURCE_H
+#define ANKI_RESOURCE_TEXTURE_RESOURCE_H
+
+#include "anki/gl/Texture.h"
+
+
+namespace anki {
+
+
+class Image;
+
+
+/// Texture resource class
+///
+/// It loads or creates an image and then loads it in the GPU. It supports 
+/// compressed and uncompressed TGAs and some of the formats of PNG 
+/// (PNG loading uses libpng)
+class TextureResource: public Texture
+{
+public:
+	/// Load a texture
+	void load(const char* filename);
+
+	/// Load a texture
+	void load(const Image& img);
+};
+
+
+} // end namespace
+
+
+#endif

+ 1 - 1
anki/scene/Renderable.cpp

@@ -1,6 +1,6 @@
 #include "anki/scene/Renderable.h"
 #include "anki/resource/Material.h"
-#include "anki/resource/Texture.h"
+#include "anki/resource/TextureResource.h"
 #include <boost/foreach.hpp>
 
 

+ 1 - 29
anki/scene/Renderable.h

@@ -53,19 +53,11 @@ private:
 class Renderable
 {
 public:
-	/// Renderable flags
-	enum RenderableFlag
-	{
-		RF_NONE = 0,
-		RF_VISIBLE = 1 ///< Visible or not. The visibility tester sets it
-	};
-
 	typedef std::vector<PropertyBase*> Properties;
 	typedef boost::iterator_range<Properties::iterator> MutableRange;
 	typedef boost::iterator_range<Properties::const_iterator> ConstRange;
 
 	Renderable()
-		: flags(RF_NONE)
 	{}
 
 	virtual ~Renderable()
@@ -77,6 +69,7 @@ public:
 	/// Access the material
 	virtual const Material& getMaterial() const = 0;
 
+	/// Information for movables
 	virtual const Transform* getRenderableWorldTransform() const
 	{
 		return nullptr;
@@ -92,32 +85,11 @@ public:
 		return ConstRange(props.begin(), props.end());
 	}
 
-	/// @name Flag manipulation
-	/// @{
-	void enableFlag(RenderableFlag flag, bool enable = true)
-	{
-		flags = enable ? flags | flag : flags & ~flag;
-	}
-	void disableFlag(RenderableFlag flag)
-	{
-		enableFlag(flag, false);
-	}
-	bool isFlagEnabled(RenderableFlag flag) const
-	{
-		return flags & flag;
-	}
-	uint getFlagsBitmask() const
-	{
-		return flags;
-	}
-	/// @}
-
 protected:
 	void init(PropertyMap& pmap);
 
 private:
 	Properties props;
-	uint flags; ///< Bitmask
 };
 
 

+ 32 - 1
anki/scene/Spatial.h

@@ -17,11 +17,20 @@ namespace anki {
 class Spatial
 {
 public:
+	/// Spatial flags
+	enum SpatialFlag
+	{
+		SF_NONE = 0,
+		SF_VISIBLE = 1 ///< Visible or not. The visibility tester sets it
+	};
+
 	/// Pass the collision shape here so we can avoid the virtuals
 	Spatial(CollisionShape* cs)
-		: spatialCs(cs)
+		: spatialCs(cs), flags(SF_NONE)
 	{}
 
+	/// @name Accessors
+	/// @{
 	const CollisionShape& getSpatialCollisionShape() const
 	{
 		return *spatialCs;
@@ -30,9 +39,31 @@ public:
 	{
 		return *spatialCs;
 	}
+	/// @}
+
+	/// @name Flag manipulation
+	/// @{
+	void enableFlag(SpatialFlag flag, bool enable = true)
+	{
+		flags = enable ? flags | flag : flags & ~flag;
+	}
+	void disableFlag(SpatialFlag flag)
+	{
+		enableFlag(flag, false);
+	}
+	bool isFlagEnabled(SpatialFlag flag) const
+	{
+		return flags & flag;
+	}
+	uint getFlagsBitmask() const
+	{
+		return flags;
+	}
+	/// @}
 
 protected:
 	CollisionShape* spatialCs;
+	uint flags;
 };
 /// @}
 

+ 3 - 1
anki/scene/VisibilityTester.cpp

@@ -31,13 +31,15 @@ void VisibilityTester::test(Frustumable& cam, Scene& scene,
 
 		if(!cam.insideFrustum(*sp))
 		{
+			sp->disableFlag(Spatial::SF_VISIBLE);
 			continue;
 		}
 
+		sp->enableFlag(Spatial::SF_VISIBLE);
+
 		Renderable* r = node->getRenderable();
 		if(r)
 		{
-			r->enableFlag(Renderable::RF_VISIBLE);
 			vinfo.renderables.push_back(r);
 		}