diff --git a/include/ACGL/OpenGL/Objects/ShaderProgram.hh b/include/ACGL/OpenGL/Objects/ShaderProgram.hh index ad2ad965509a76189d2248e4ed2887f35d09d1a2..7c6d83098c30153a1c333b38968a5b033cab3abb 100644 --- a/include/ACGL/OpenGL/Objects/ShaderProgram.hh +++ b/include/ACGL/OpenGL/Objects/ShaderProgram.hh @@ -54,6 +54,9 @@ namespace ACGL{ namespace OpenGL{ +class VertexArrayObject; +ACGL_SHARED_TYPEDEF(VertexArrayObject) + class ShaderProgram { ACGL_NOT_COPYABLE(ShaderProgram) @@ -112,12 +115,17 @@ public: bool link (void) const; + // ===================================================================================================== \/ + // ============================================================================================= METHODS \/ + // ===================================================================================================== \/ +public: + //! Matches the attribute locations of this ShaderProgram to the names of the ArrayBuffer attributes currently attached to _vao + void setAttributeLocationsByVAO( const SharedVertexArrayObject& _vao ); // ===================================================================================================== \/ // ============================================================================================ UNIFORMS \/ // ===================================================================================================== \/ - - +public: // int by location inline void setUniform (GLint _location, GLint _v) const { glUniform1i (_location, _v); } inline void setUniform (GLint _location, GLsizei _n, GLint *_v)const { glUniform1iv(_location, _n, _v); } @@ -231,7 +239,7 @@ public: // ======================================================================================================= \/ // ============================================================================================ HIGH LEVEL \/ // ======================================================================================================= \/ - +public: // normal: template <typename T> inline void setUniform (const std::string& _nameInShader, T _v) const @@ -276,7 +284,6 @@ public: inline void setTexture (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLenum _unit = 0) const { setUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); } inline void setProgramTexture (GLint _location, const ConstSharedTexture& _texture, GLenum _unit = 0) const { glProgramUniform1i(mObjectName, _location, _unit); _texture->bind(_unit); } - // =================================================================================================== \/ // ============================================================================================ FIELDS \/ diff --git a/include/ACGL/OpenGL/Objects/VertexArrayObject.hh b/include/ACGL/OpenGL/Objects/VertexArrayObject.hh index 12278157495bc146ee8be954b09e0390a6a13dbe..85b4bd0d45dbbd571375ddeeebf753648c59506c 100755 --- a/include/ACGL/OpenGL/Objects/VertexArrayObject.hh +++ b/include/ACGL/OpenGL/Objects/VertexArrayObject.hh @@ -56,6 +56,12 @@ public: // more Attribute properties can be looked up in the ArrayBuffer (like the name) }; + // ===================================================================================================== \/ + // ============================================================================================ TYPEDEFS \/ + // ===================================================================================================== \/ +public: + typedef std::vector< Attribute > AttributeVec; + // ========================================================================================================= \/ // ============================================================================================ CONSTRUCTORS \/ // ========================================================================================================= \/ @@ -88,9 +94,10 @@ public: // ============================================================================================ GETTERS \/ // ==================================================================================================== \/ public: - inline GLuint operator() (void) const { return mObjectName; } - inline GLuint getObjectName(void) const { return mObjectName; } - inline GLenum getMode(void) const { return mMode; } + inline GLuint operator() (void) const { return mObjectName; } + inline GLuint getObjectName(void) const { return mObjectName; } + inline const AttributeVec& getAttributes(void) const { return mAttributes; } + inline GLenum getMode (void) const { return mMode; } // ==================================================================================================== \/ // ============================================================================================ METHODS \/ @@ -231,7 +238,7 @@ public: * Return true if setAttributeMappingsByShaderProgram(_shaderProgram) would do nothing. * That means the VAO and ShaderProgram have already matching layouts. */ - bool mappingsMatchShaderProgram( const ConstSharedShaderProgram &_shaderProgram ) const + bool mappingsMatchShaderProgram( const SharedShaderProgram &_shaderProgram ) const { for (AttributeVec::size_type i = 0; i < mAttributes.size(); ++i) { @@ -247,7 +254,7 @@ public: * Query the attribute locations based on the attribute names in the ArrayBuffers and the ShaderProgram * If they match, use the location reported from the ShaderProgram. */ - void setAttributeLocationsByShaderProgram( const ConstSharedShaderProgram &_shaderProgram ) + void setAttributeLocationsByShaderProgram( const SharedShaderProgram &_shaderProgram ) { bool fullUpdateNeeded = false; @@ -394,12 +401,6 @@ public: drawArrays(mAttributes[0].arrayBuffer->getElements()); } - // ===================================================================================================== \/ - // ============================================================================================ TYPEDEFS \/ - // ===================================================================================================== \/ -protected: - typedef std::vector< Attribute > AttributeVec; - // =================================================================================================== \/ // ============================================================================================ FIELDS \/ // =================================================================================================== \/ diff --git a/src/ACGL/OpenGL/Objects/ShaderProgram.cc b/src/ACGL/OpenGL/Objects/ShaderProgram.cc index 06197e99d48444bda8c37e7f9917add9577653f8..cb08ef28c6b8317250c68906e2135c00e301e696 100644 --- a/src/ACGL/OpenGL/Objects/ShaderProgram.cc +++ b/src/ACGL/OpenGL/Objects/ShaderProgram.cc @@ -4,6 +4,7 @@ //////////////////////////////////////////////////////////////////////////////// #include <ACGL/OpenGL/Objects/ShaderProgram.hh> +#include <ACGL/OpenGL/Objects/VertexArrayObject.hh> #include <ACGL/OpenGL/Tools.hh> using namespace ACGL::OpenGL; @@ -47,3 +48,33 @@ bool ShaderProgram::link(void) const #endif return true; } + +void ShaderProgram::setAttributeLocationsByVAO( const SharedVertexArrayObject& _vao ) +{ + bool needsRelink = false; + + // search through all attributes of _vao + VertexArrayObject::AttributeVec vaoAttributes = _vao->getAttributes(); + for(VertexArrayObject::AttributeVec::size_type i = 0; i < vaoAttributes.size(); ++i) + { + if(vaoAttributes[i].location == -1) + continue; + + // find the name of the current attribute in its ArrayBuffer + std::string arrayBufferAttributeName = vaoAttributes[i].arrayBuffer->getAttributes()[vaoAttributes[i].attributeID].name; + + // find out whether an attribute with a matching name exists in this ShaderProgram + GLint attribLocation = getAttributeLocation(arrayBufferAttributeName); + if(attribLocation != -1 // attribute with that name exists? + && attribLocation != vaoAttributes[i].location) // attribute with that name not already bound correctly? + { + bindAttributeLocation(arrayBufferAttributeName, vaoAttributes[i].location); + + needsRelink = true; + } + } + + // re-link the program only if necessary + if(needsRelink) + link(); +}