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();
+}