diff --git a/include/ACGL/Base/FileHelpers.hh b/include/ACGL/Base/FileHelpers.hh
index e24b5a6e071f44845081f533da5eb9fb6f632891..d80270ce1e92b918fc74c32c570c6e9af130c5a1 100644
--- a/include/ACGL/Base/FileHelpers.hh
+++ b/include/ACGL/Base/FileHelpers.hh
@@ -48,7 +48,7 @@ namespace FileHelpers
     /*
      * Splits a string at the delim char.
      */
-    //void splitString(const std::string &s, char delim, std::vector<std::string> &elems);
+    void splitString(const std::string &s, char delim, std::vector<std::string> &elems);
 
 
     /*
diff --git a/include/ACGL/OpenGL/Objects/ArrayBuffer.hh b/include/ACGL/OpenGL/Objects/ArrayBuffer.hh
index 5bfa2afa6d4d1d43983c6ac46fdfd7dee3999d4b..24b3f729a3bffb8c5a348871503e56c7eb9ef399 100644
--- a/include/ACGL/OpenGL/Objects/ArrayBuffer.hh
+++ b/include/ACGL/OpenGL/Objects/ArrayBuffer.hh
@@ -118,6 +118,9 @@ public:
     //! Returns the definitions of the attributes:
     inline const AttributeVec& getAttributes (void) const { return mAttributes; }
 
+    //! Returns one attribute:
+    inline Attribute getAttribute( uint_t i ) const { return mAttributes[i]; }
+
     // ==================================================================================================== \/
     // ============================================================================================ METHODS \/
     // ==================================================================================================== \/
diff --git a/include/ACGL/OpenGL/Objects/LocationMappings.hh b/include/ACGL/OpenGL/Objects/LocationMappings.hh
index e59948cec549e1ec8a585ada17f3121830042936..d8fc70bc3647f3ddb2f3f1ff7a3aa29e52d55440 100644
--- a/include/ACGL/OpenGL/Objects/LocationMappings.hh
+++ b/include/ACGL/OpenGL/Objects/LocationMappings.hh
@@ -77,6 +77,8 @@ public:
     //! Tells whether a mapping for a given name exists
     inline bool exists(const std::string& _name) const { return (getLocation(_name) != -1); }
 
+    void printMapping();
+
     // =================================================================================================== \/
     // ============================================================================================ FIELDS \/
     // =================================================================================================== \/
diff --git a/include/ACGL/OpenGL/Objects/VertexArrayObject.hh b/include/ACGL/OpenGL/Objects/VertexArrayObject.hh
index f9f14a55fc90fedd9ff62497d71c14b708bf7259..78c38a387418aa7ebb075733e6ba0301cf702f66 100755
--- a/include/ACGL/OpenGL/Objects/VertexArrayObject.hh
+++ b/include/ACGL/OpenGL/Objects/VertexArrayObject.hh
@@ -54,7 +54,7 @@ public:
     {
         SharedArrayBuffer arrayBuffer; // the ArrayBuffer to use
         int32_t           attributeID; // the attribute from that ArrayBuffer
-        GLint             location;    // a location the in-attribute from a shader is bound to
+        //GLint             location;    // a location the in-attribute from a shader is bound to
         // more Attribute properties can be looked up in the ArrayBuffer (like the name)
     };
 
@@ -62,7 +62,7 @@ public:
     // ============================================================================================ TYPEDEFS \/
     // ===================================================================================================== \/
 public:
-    typedef std::vector< Attribute > AttributeVec;
+    typedef std::vector< Attribute > AttributeVec; // position in the vector == attrib location
 
     // ========================================================================================================= \/
     // ============================================================================================ CONSTRUCTORS \/
@@ -75,9 +75,14 @@ public:
         mMode(GL_TRIANGLES)
     {
         glGenVertexArrays(1, &mObjectName);
+        GLint maxAttributes;
+        glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttributes);
+
         if (openGLCriticalErrorOccured() ) {
             ACGL::Utils::error() << "could not generate vertex array object!" << std::endl;
         }
+
+        mAttributes.resize( maxAttributes ); // reserve probably 16 slots, the size() can now be used to query the MAX_VERTEX_ATTRIBS
     }
 
     virtual ~VertexArrayObject(void)
@@ -120,13 +125,6 @@ public:
     // ============================================================================================ METHODS \/
     // ==================================================================================================== \/
 public:
-    /**
-     * Will check if the VAO looks ok (e.g. there is at least one ArrayBuffer and all ArrayBuffers
-     * have the same number of elements).
-     * A failed test will output an error but won't have other consequences.
-     */
-    bool isValid(void) const;
-
     /**
      * Set the given ElementArrayBuffer, if a NULL pointer is given, an existing EAB will get unset.
      * Will restore the previously bound VAO (DSA style)
@@ -140,21 +138,21 @@ public:
      * Will set the attribute _arrayBufferAttribute of ArrayBuffer _arrayBuffer to the given attribute location.
      * If that location was already used it will get overwritten.
      * The _attributeLocation has to be lower than GL_MAX_VERTEX_ATTRIBS
-     * An attribute location of -1 indicates that the attribute should remain unbound for now
+     * An attribute location of -1 indicates that the attribute should get the next free location
      */
     inline void attachAttribute( const SharedArrayBuffer& _arrayBuffer,
                                  uint32_t _arrayBufferAttribute,
                                  GLint    _attributeLocation = -1)
     {
-        Attribute newAttribute = { _arrayBuffer, _arrayBufferAttribute, _attributeLocation };
-        attachAttribute( newAttribute );
+        Attribute newAttribute = { _arrayBuffer, _arrayBufferAttribute };
+        attachAttribute( newAttribute, _attributeLocation );
     }
 
     /**
      * Will set the attribute named _arrayBufferAttributeName of ArrayBuffer _arrayBuffer to the given attribute location.
      * If that location was already used it will get overwritten.
      * The _attributeLocation has to be lower than GL_MAX_VERTEX_ATTRIBS
-     * An attribute location of -1 indicates that the attribute should remain unbound for now
+     * An attribute location of -1 indicates that the attribute should should get the next free location
      */
     inline void attachAttribute( const SharedArrayBuffer& _arrayBuffer,
                                  const std::string& _arrayBufferAttributeName,
@@ -165,19 +163,21 @@ public:
                         _attributeLocation);
     }
 
-    void attachAttribute( const Attribute &_attribute );
+    //! if the location was already in use, the new attribute will replace it, if a free loc should be used but no location is free,
+    //! nothing will get attached.
+    void attachAttribute( const Attribute &_attribute, GLint _location );
 
     /**
      * Attaches all attributes defined by an ArrayBuffer
-     * The attributes are attached to the default location of -1, indicating they should remain unbound for now
+     * The attributes are attached to the next free location.
      * Afterwards, you might want to automatically wire up the attributes with a ShaderProgram, using setAttributeLocationsByShaderProgram
      */
     void attachAllAttributes( const SharedArrayBuffer& _arrayBuffer );
 
     /**
-     * Will detach the first found Attribute with the given attribute location.
+     * Will detach the Attribute with the given attribute location.
      */
-    void detachAttribute( GLint _location );
+    void detachAttribute( GLuint _location );
 
     /**
      * Will detach the first found Attribute with the given name.
@@ -190,11 +190,17 @@ public:
      */
     void setAttributeLocations( ConstSharedLocationMappings _locationMappings );
 
+    //! get a list of attribute locations and names that can be used to set up a ShaderProgram
+    SharedLocationMappings getAttributeLocations();
+
 private:
-    //! Sets the vertex attribute pointer for the current VAO according to the specified attribute data
+    //! Sets the vertex attribute pointer for the current VAO according to the specified attribute (index into mAttributes)
     //! Note: expects that this VAO is currently bound
     //! Note: will bind the ArrayBuffer referenced by _attribute.arrayBuffer
-    void setAttributePointer(const Attribute& _attribute);
+    void setAttributePointer( GLuint _index );
+
+    //! returns a free attribute location between 0 .. MAX_ATTRIB_LOCATIONS unless no location is free, in that case returns -1
+    GLint getFreeAttributeLocation();
 
     // ===================================================================================================== \/
     // ============================================================================================ WRAPPERS \/
diff --git a/src/ACGL/Base/FileHelpers.cc b/src/ACGL/Base/FileHelpers.cc
index 22b8f2f384285fc9340b4edb44f09b213f28045c..7b037de49a12666e5654286ffb6aa7018a4adecf 100644
--- a/src/ACGL/Base/FileHelpers.cc
+++ b/src/ACGL/Base/FileHelpers.cc
@@ -73,6 +73,8 @@ namespace FileHelpers
         return false;
     }
 
+    */
+
     // copied from stackoverflow
     void splitString(const std::string &s, char delim, std::vector<std::string> &elems)
     {
@@ -87,7 +89,6 @@ namespace FileHelpers
             elems.push_back(item);
         }
     }
-    */
 
     #ifndef PLATFORM_IOS
     std::string getDeviceDependentPathFor( const std::string &resource )
diff --git a/src/ACGL/OpenGL/Objects/LocationMappings.cc b/src/ACGL/OpenGL/Objects/LocationMappings.cc
index 204e9be1fbc7feda09e6852e397cb3da79466066..49c1db092fa8d4f14ab89d5daaed61e94fbbce94 100644
--- a/src/ACGL/OpenGL/Objects/LocationMappings.cc
+++ b/src/ACGL/OpenGL/Objects/LocationMappings.cc
@@ -31,3 +31,12 @@ void LocationMappings::setLocation(const std::string& _name, GLuint _location)
     }
     mMappings[_name] = _location;
 }
+
+
+void LocationMappings::printMapping()
+{
+    LocationMap::const_iterator end = mMappings.end();
+    for (LocationMap::const_iterator it = mMappings.begin(); it != end; ++it) {
+        ACGL::Utils::debug() << "loc mapping: " << it->first << " - " << it->second << std::endl;
+    }
+}
diff --git a/src/ACGL/OpenGL/Objects/Sampler.cc b/src/ACGL/OpenGL/Objects/Sampler.cc
index e149ab53395669c3df8ddd6768163ec0d1eaaa99..20cc9cfe111eaa9d20209707ec1966020c445537 100644
--- a/src/ACGL/OpenGL/Objects/Sampler.cc
+++ b/src/ACGL/OpenGL/Objects/Sampler.cc
@@ -5,6 +5,8 @@
 
 #include <ACGL/OpenGL/Objects/Sampler.hh>
 
+#if (ACGL_OPENGL_VERSION >= 33)
+
 using namespace ACGL::OpenGL;
 
 Sampler::Sampler()
@@ -46,3 +48,4 @@ void Sampler::setMaxAnisotropy( GLfloat _sampleCount )
     }
 }
 
+#endif // OpenGL >= 3.3
diff --git a/src/ACGL/OpenGL/Objects/VertexArrayObject.cc b/src/ACGL/OpenGL/Objects/VertexArrayObject.cc
index 0bf45513a783c35c7b293c8f0df691f5affe9aad..2d953fae6b89d1811f28b1a282c72a41932d0513 100755
--- a/src/ACGL/OpenGL/Objects/VertexArrayObject.cc
+++ b/src/ACGL/OpenGL/Objects/VertexArrayObject.cc
@@ -7,6 +7,7 @@
 #if (ACGL_OPENGL_VERSION >= 30)
 
 using namespace ACGL;
+using namespace ACGL::Utils;
 using namespace ACGL::OpenGL;
 
 void VertexArrayObject::attachElementArrayBuffer( const SharedElementArrayBuffer& _elementArrayBuffer )
@@ -27,36 +28,67 @@ void VertexArrayObject::attachElementArrayBuffer( const SharedElementArrayBuffer
     restoreOldVAO();
 }
 
-void VertexArrayObject::attachAttribute( const Attribute &_attribute )
+void VertexArrayObject::attachAttribute( const Attribute &_attribute, GLint _location )
 {
-    GLint maxAttributes;
-    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttributes); // TODO: clever caching
-
-    if(mAttributes.size() >= (uint32_t) maxAttributes)
-    {
+    if ( (GLuint)_location >= mAttributes.size()) {
         ACGL::Utils::error() << "can't attach attribute " << _attribute.arrayBuffer->getAttributes()[_attribute.attributeID].name
-                             << " - maximum number of attributes reached: " << maxAttributes << std::endl;
+                             << " - maximum number of attributes: " << mAttributes.size() << std::endl;
         return;
+    } else if (_location < 0) {
+        // find a free location:
+        _location = getFreeAttributeLocation();
+        if (_location < 0) {
+            // no free location found
+            ACGL::Utils::error() << "can't attach attribute " << _attribute.arrayBuffer->getAttributes()[_attribute.attributeID].name
+                                 << " - maximum number of attributes reached ( " << mAttributes.size() << " )" << std::endl;
+            return;
+        }
     }
 
-    mAttributes.push_back( _attribute );
-
+    mAttributes[_location] = _attribute;
     storeOldVAOandBind();
-    setAttributePointer( _attribute );
+    setAttributePointer( _location );
     restoreOldVAO();
 }
 
+GLint VertexArrayObject::getFreeAttributeLocation()
+{
+    GLint maxAttributes;
+    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttributes);
+
+    for (ArrayBuffer::AttributeVec::size_type i = 0; i < mAttributes.size(); ++i)
+    {
+        if ( !(mAttributes[i].arrayBuffer) ) {
+            // no shared pointer set, no attribute set!
+            return (GLint) i;
+        }
+    }
+
+    return -1;
+}
+
 void VertexArrayObject::attachAllAttributes( const SharedArrayBuffer& _arrayBuffer )
 {
     ArrayBuffer::AttributeVec attributes = _arrayBuffer->getAttributes();
     for(ArrayBuffer::AttributeVec::size_type i = 0; i < attributes.size(); ++i)
     {
-        attachAttribute(_arrayBuffer, (GLint) i);
+        attachAttribute(_arrayBuffer, (GLint) i, getFreeAttributeLocation() );
     }
 }
 
-void VertexArrayObject::detachAttribute( GLint _location )
+void VertexArrayObject::detachAttribute( GLuint _location )
 {
+    if (_location >= mAttributes.size()) {
+        ACGL::Utils::error() << "can't detach attribute with location " << _location << " - no such Attribute" << std::endl;
+        return;
+    }
+
+    storeOldVAOandBind();
+    mAttributes[_location].arrayBuffer = SharedArrayBuffer();
+    glDisableVertexAttribArray( _location );
+    restoreOldVAO();
+
+    /*
     for (AttributeVec::size_type i = 0; i < mAttributes.size(); ++i)
     {
         if (mAttributes[i].location == _location)
@@ -69,6 +101,7 @@ void VertexArrayObject::detachAttribute( GLint _location )
     }
     // if we got here, no Attribute of the given name exists
     ACGL::Utils::warning() << "can't detach attribute with location " << _location << " - no such Attribute" << std::endl;
+    */
 }
 
 /**
@@ -80,9 +113,10 @@ void VertexArrayObject::detachAttribute( const std::string &_name )
     {
         if (mAttributes[i].arrayBuffer->getAttributes()[ mAttributes[i].attributeID ].name == _name)
         {
+            detachAttribute( i );
             // the other pointer data is still set, but that isn't relevant if the attribute itself is deactivated
-            glDisableVertexArrayAttribEXT( mObjectName, mAttributes[i].location );
-            mAttributes.erase( mAttributes.begin()+i );
+            //glDisableVertexArrayAttribEXT( mObjectName, mAttributes[i].location );
+            //mAttributes.erase( mAttributes.begin()+i );
             return;
         }
     }
@@ -90,108 +124,83 @@ void VertexArrayObject::detachAttribute( const std::string &_name )
     ACGL::Utils::warning() << "can't detach attribute " << _name << " - no such Attribute" << std::endl;
 }
 
-bool VertexArrayObject::isValid(void) const
-{
-    GLsizei elements = 0;
 
-    if (mAttributes.size() > 0)
-    {
-        elements = mAttributes[0].arrayBuffer->getElements();
-    } else {
-        Utils::error() << "VertexArrayObject has no attributes attached" << std::endl;
-        return false;
-    }
-    if (mpElementArrayBuffer)
+void VertexArrayObject::setAttributeLocations( ConstSharedLocationMappings _locationMappings )
+{
+    AttributeVec oldAttributes = mAttributes;
+    for (AttributeVec::size_type i = 0; i < mAttributes.size(); ++i)
     {
-        elements = mpElementArrayBuffer->getElements();
+        mAttributes[i].arrayBuffer = SharedArrayBuffer(); // set to NULL
     }
+    AttributeVec unmatchedAttributes;
 
-    for (AttributeVec::size_type i = 0; i < mAttributes.size(); ++i)
+    // if there is an old attribute, look up the name in the _locationMap, use the new location if the
+    // name is present (stored in the map), remove the attribute from the old map.
+    // after that, run over the unmatchedAttributes to store the remaining attributes on free slots in the map
+    for (AttributeVec::size_type i = 0; i < oldAttributes.size(); ++i)
     {
-        if (mAttributes[0].arrayBuffer->getElements() != elements)
-        {
-            Utils::error() << "VertexArrayObject validation failed: Attribute "<< i << " has different number of elements."<< std::endl;
-            return false;
+        if (oldAttributes[i].arrayBuffer) {
+            GLint location = _locationMappings->getLocation( oldAttributes[i].arrayBuffer->getAttribute( (int) oldAttributes[i].attributeID ).name );
+            if ((location >= 0) && ((GLuint)location < oldAttributes.size())) {
+                mAttributes[location] = oldAttributes[i];
+                //debug() << "moved  loc " << oldAttributes[i].arrayBuffer->getAttribute( (int) oldAttributes[i].attributeID ).name
+                //        << " from " << i << " to " << location << std::endl;
+            } else {
+                unmatchedAttributes.push_back( oldAttributes[i] );
+                //debug() << "unmatched " << oldAttributes[i].arrayBuffer->getAttribute( (int) oldAttributes[i].attributeID ).name
+                //        << " at " << i << std::endl;
+            }
+
+            oldAttributes[i].arrayBuffer = SharedArrayBuffer(); // set to NULL
         }
     }
+    for (AttributeVec::size_type i = 0; i < unmatchedAttributes.size(); ++i)
+    {
+        GLint location = getFreeAttributeLocation();
+        mAttributes[location] = unmatchedAttributes[i]; // the total attribute number hasn't changed so location must be valid
+        //debug() << "moved uloc " << unmatchedAttributes[i].arrayBuffer->getAttribute( (int) unmatchedAttributes[i].attributeID ).name
+        //        << " to " << location << std::endl;
+    }
 
-    return true;
-}
+    storeOldVAOandBind();
+    // disable all attributes & set the new ones
+    for (GLuint i = 0; i < mAttributes.size(); ++i) {
+        glDisableVertexAttribArray( i );
 
+        if (mAttributes[i].arrayBuffer) setAttributePointer( i );
+    }
+    restoreOldVAO();
+}
 
 
-void VertexArrayObject::setAttributeLocations( ConstSharedLocationMappings _locationMappings )
+SharedLocationMappings VertexArrayObject::getAttributeLocations()
 {
-    bool fullUpdateNeeded = false;
-    GLint maxAttributes;
-    glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &maxAttributes );
+    SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
 
     for (AttributeVec::size_type i = 0; i < mAttributes.size(); ++i)
     {
-        std::string attributeName = mAttributes[i].arrayBuffer->getAttributes()[ mAttributes[i].attributeID ].name;
-        int_t       location      = _locationMappings->getLocation(attributeName);
-
-        if(location == -1)
-        {
-            // TODO: fail silently?
-            ACGL::Utils::error() << "can't update VAO mapping: attribute " << attributeName << " not specified" << std::endl;
-            continue; // try to match as much as possible
-        }
-        if(location >= maxAttributes)
-        {
-            ACGL::Utils::error() << "can't update VAO mapping: location of attribute " << attributeName << " is too high ("
-                                 << location << ") GL_MAX_VERTEX_ATTRIBS is " << maxAttributes << std::endl;
-            continue; // try to match as much as possible
-        }
-
-        if(mAttributes[i].location != location)
-        {
-            mAttributes[i].location = location;
-            fullUpdateNeeded = true;
+        if ( mAttributes[i].arrayBuffer ) {
+            //debug() << "aloc: " << mAttributes[i].arrayBuffer->getAttribute( (int) mAttributes[i].attributeID ).name << " " << i << std::endl;
+            locationMap->setLocation( mAttributes[i].arrayBuffer->getAttribute( (int) mAttributes[i].attributeID ).name, i );
         }
     }
 
-    // why the full update? setting the new location right when a change is detected will get problamatic
-    // if two attributes exchange there position...
-    if (fullUpdateNeeded)
-    {
-        storeOldVAOandBind();
-
-        // disable all attributes
-        for (GLint i = 0; i < maxAttributes; ++i)
-            glDisableVertexAttribArray( i );
-
-        // set all attributes:
-        for (uint32_t i = 0; i < mAttributes.size(); ++i)
-        {
-            setAttributePointer(mAttributes[i]);
-        }
-
-        restoreOldVAO();
-    }
+    return locationMap;
 }
 
-
-void VertexArrayObject::setAttributePointer(const Attribute& _attribute)
+void VertexArrayObject::setAttributePointer( GLuint _index )
 {
-    if(_attribute.location == -1)
-    {
-        // An attribute location of -1 indicates that this attribute should remain unbound for now
-        return;
-    }
-
-    SharedArrayBuffer arrayBuffer = _attribute.arrayBuffer;
-    arrayBuffer->bind();
+    mAttributes[_index].arrayBuffer->bind();
 
-    ArrayBuffer::Attribute arrayBufferAttribute = arrayBuffer->getAttributes()[_attribute.attributeID];
-    glVertexAttribPointer(_attribute.location,
+    ArrayBuffer::Attribute arrayBufferAttribute = mAttributes[_index].arrayBuffer->getAttribute(mAttributes[_index].attributeID);
+    glVertexAttribPointer(_index,
                           arrayBufferAttribute.size,
                           arrayBufferAttribute.type,
                           arrayBufferAttribute.normalized,
-                          arrayBuffer->getStride(),
+                          mAttributes[_index].arrayBuffer->getStride(),
                           reinterpret_cast<GLvoid*>(arrayBufferAttribute.offset)
                           );
-    glEnableVertexAttribArray(_attribute.location);
+    glEnableVertexAttribArray(_index);
 }