diff --git a/include/ACGL/OpenGL/Objects/FrameBufferObject.hh b/include/ACGL/OpenGL/Objects/FrameBufferObject.hh
index 1085e78e153b9bac622134dc096324f73644f983..09656c6b408f9080e10870008f2457e9c8b66d9b 100644
--- a/include/ACGL/OpenGL/Objects/FrameBufferObject.hh
+++ b/include/ACGL/OpenGL/Objects/FrameBufferObject.hh
@@ -30,7 +30,7 @@
 #include <ACGL/OpenGL/Tools.hh>
 #include <ACGL/OpenGL/Objects/RenderBuffer.hh>
 #include <ACGL/OpenGL/Objects/Texture.hh>
-#include <ACGL/OpenGL/Objects/ShaderProgram.hh>
+//#include <ACGL/OpenGL/Objects/ShaderProgram.hh>
 #include <ACGL/OpenGL/Objects/LocationMappings.hh>
 
 #include <vector>
@@ -43,12 +43,6 @@ class FrameBufferObject
 {
     ACGL_NOT_COPYABLE(FrameBufferObject)
 
-    // =================================================================================================== \/
-    // ============================================================================================ STATIC \/
-    // =================================================================================================== \/
-private:
-    static GLuint msBuffers[8];
-
     // ==================================================================================================== \/
     // ============================================================================================ STRUCTS \/
     // ==================================================================================================== \/
@@ -56,10 +50,10 @@ public:
     //! An attachment can be a texture or a render buffer
     struct Attachment
     {
-        std::string name;
-        ConstSharedTexture texture;
-        ConstSharedRenderBuffer renderBuffer;
-        int_t fragDataLocation; // the frag data location that maps to this attachment
+        std::string             name;         // user defined name that matches the fragment shader out
+        ConstSharedTexture      texture;      // attached color texture, or:
+        ConstSharedRenderBuffer renderBuffer; // attached renderbuffer - only this or the texture should be set!
+        GLuint                  location;     // the frag data location that maps to this attachment
     };
 
     // ===================================================================================================== \/
@@ -74,10 +68,7 @@ public:
 public:
     FrameBufferObject(void)
     :   mObjectName(0),
-        mDrawBuffers(0),
         mColorAttachments(),
-        mColorAttachmentIndices(),
-        mFragDataLocationIndices(),
         mDepthAttachment()
     {
         glGenFramebuffers(1, &mObjectName);
@@ -86,9 +77,10 @@ public:
             ACGL::Utils::error() << "could not generate FrameBufferObject!" << std::endl;
             return;
         }
-        mDepthAttachment.name = "";
-        mDepthAttachment.texture = ConstSharedTexture();
+        mDepthAttachment.texture      = ConstSharedTexture();
         mDepthAttachment.renderBuffer = ConstSharedRenderBuffer();
+        mDepthAttachment.name     = ""; // not useful here
+        mDepthAttachment.location = -1; // not useful here
     }
 
     virtual ~FrameBufferObject(void)
@@ -140,56 +132,36 @@ public:
         openGLRareError();
     }*/
 
+    //! let OpenGL validate the completeness
     bool isFrameBufferObjectComplete() const;
 
-    inline bool attachColorRenderBuffer(const std::string _name, const ConstSharedRenderBuffer& _renderBuffer)
+    /*
+     * Attach another RenderBuffer as a render target. If the name already exists the old target will get replaced.
+     */
+    inline bool attachColorRenderBuffer(const std::string &_name, const ConstSharedRenderBuffer& _renderBuffer)
     {
-        bind();
-        glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mDrawBuffers, GL_RENDERBUFFER, _renderBuffer->getObjectName() );
-        if (openGLCommonErrorOccured())
-        {
-            Utils::error() << "Attaching of render buffer to the FBO failed" << std::endl;
-            return false;
-        }
-
-        Attachment attachment = {_name, SharedTexture(), _renderBuffer};
-        mColorAttachments.push_back(attachment);
-        mColorAttachmentIndices[_name] = mDrawBuffers;
-        mFragDataLocationIndices[mDrawBuffers] = mDrawBuffers;
-        mDrawBuffers++;
-        return true;
+        return attachColorAttachment( (Attachment){_name, SharedTexture(), _renderBuffer, mColorAttachments.size()} );
     }
 
-    inline bool attachColorTexture(const std::string _name, const ConstSharedTexture& _texture)
+    inline bool attachColorTexture(const std::string &_name, const ConstSharedTexture& _texture)
     {
-        bind();
-        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mDrawBuffers, _texture->getTarget(), _texture->getObjectName(), 0 );
-        if (openGLCommonErrorOccured())
-        {
-            Utils::error() << "Attaching of texture to the FBO failed" << std::endl;
-            return false;
-        }
-
-        Attachment attachment = {_name, _texture, SharedRenderBuffer()};
-        mColorAttachments.push_back(attachment);
-        mColorAttachmentIndices[_name] = mDrawBuffers;
-        mFragDataLocationIndices[mDrawBuffers] = mDrawBuffers;
-        mDrawBuffers++;
-        return true;
+        return attachColorAttachment( (Attachment){_name, _texture, SharedRenderBuffer(), mColorAttachments.size()} );
     }
 
-    inline bool setColorRenderBuffer(const std::string _name, const ConstSharedRenderBuffer& _renderBuffer)
+    inline bool attachColorRenderBuffer(const std::string &_name, const ConstSharedRenderBuffer& _renderBuffer, GLuint _location )
     {
-        glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[_name], GL_RENDERBUFFER, _renderBuffer->getObjectName() );
-        return true;
+        return attachColorAttachment( (Attachment){_name, SharedTexture(), _renderBuffer, _location} );
     }
 
-    inline bool setColorTexture(const std::string _name, const ConstSharedTexture& _texture)
+    inline bool attachColorTexture(const std::string &_name, const ConstSharedTexture& _texture, GLuint _location )
     {
-        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[_name], _texture->getTarget(), _texture->getObjectName(), 0 );
-        return true;
+        return attachColorAttachment( (Attachment){_name, _texture, SharedRenderBuffer(), _location} );
     }
 
+    bool attachColorAttachment( const Attachment &_attachment );
+
+    void remapAttachments();
+
     inline bool setDepthRenderBuffer(const ConstSharedRenderBuffer& _renderBuffer)
     {
         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffer->getObjectName() );
@@ -226,30 +198,20 @@ public:
     // =========================================================================================== METHODS \/
     // =================================================================================================== \/
 public:
-
-    //! updates the attachment locations of this FBO so they match the locations of fragment shader output
-    //! variables of the same names in _shaderPorgram
-    void setAttachmentsByShaderProgram(ConstSharedShaderProgram _shaderProgram);
-
     //! sets the attachment locations of this FBO where they match the names specified in _locationMappings
     void setAttachmentLocations(ConstSharedLocationMappings _locationMappings);
 
-protected:
-    //! maps the frag data locations specified in mFragDataLocationIndices to the respective color attachments
-    void updateDrawBuffers();
+    //! get a list of attachment locations and names that can be used to set up a ShaderProgram
+    SharedLocationMappings getAttachmentLocations();
 
     // =================================================================================================== \/
     // ============================================================================================ FIELDS \/
     // =================================================================================================== \/
 protected:
     GLuint        mObjectName;
-    GLsizei       mDrawBuffers;
     AttachmentVec mColorAttachments;
-
-    std::map<std::string, int> mColorAttachmentIndices; // maps color attachment names to attachment indices (GL_COLOR_ATTACHMENT0 + i)
-    std::map<int, int> mFragDataLocationIndices;        // maps fragment data locations to attachment indices (GL_COLOR_ATTACHMENT0 + i)
-
-    Attachment    mDepthAttachment;  // depth and stencil are combined
+    Attachment    mDepthAttachment;   // depth and stencil are combined
+    GLuint        mBufferMappings[8]; // maps from mColorAttachment.loction (shader outs) to FBO locations (order of mColorAttachments)
 };
 
 ACGL_SHARED_TYPEDEF(FrameBufferObject)
diff --git a/include/ACGL/OpenGL/Objects/ShaderProgram.hh b/include/ACGL/OpenGL/Objects/ShaderProgram.hh
index e1dd512fea3bcd4651416c8f84b642247f3c6079..8ed1dcb6ae9fbd85aa5f613304ad39b03810842b 100644
--- a/include/ACGL/OpenGL/Objects/ShaderProgram.hh
+++ b/include/ACGL/OpenGL/Objects/ShaderProgram.hh
@@ -99,39 +99,51 @@ public:
     // ============================================================================================ WRAPPERS \/
     // ===================================================================================================== \/
 public:
-    inline GLint getUniformLocation      (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }
-    inline GLint getAttributeLocation    (const std::string& _nameInShader) const { return glGetAttribLocation  (mObjectName, _nameInShader.c_str()); }
-    inline void bindAttributeLocation    (const std::string& _nameInShader, GLuint _location) const { glBindAttribLocation   (mObjectName, _location, _nameInShader.c_str()); }
-
-#if (ACGL_OPENGL_VERSION >= 30)
-    inline GLint getFragmentDataLocation (const std::string& _nameInShader) const { return glGetFragDataLocation(mObjectName, _nameInShader.c_str()); }
-    inline void bindFragmentDataLocation (const std::string& _nameInShader, GLuint _location) const { glBindFragDataLocation (mObjectName, _location, _nameInShader.c_str()); }
-#endif // OpenGL >= 3.0
-
+    //! use, or activate it for rendering, also needed to set uniforms:
     inline void use(void) const { glUseProgram(mObjectName); }
 
+    //! attach a single shader, don't forget to relink!
     inline void attachShader(const ConstSharedShader& _shader)
     {
         mShaders.push_back(_shader);
         glAttachShader( mObjectName, _shader->getObjectName() );
     }
 
+    //! link the program, has to be redone after changing input or output locations:
     bool link (void) const;
 
     // ===================================================================================================== \/
-    // ============================================================================================= METHODS \/
+    // =========================================================================================== LOCATIONS \/
     // ===================================================================================================== \/
-public:
-    // Matches the attribute locations of this ShaderProgram to the names of the ArrayBuffer attributes currently attached to _vao
-    //void setAttributeLocationsByVAO( ConstSharedVertexArrayObject _vao );
-    // Matches the fragment data locations of this ShaderProgram to the names of the color attachments of _fbo
-    //void setFragmentDataLocationsByFBO( ConstSharedFrameBufferObject _fbo );
+
+    //////////// uniform locations:
+    inline GLint getUniformLocation      (const std::string& _nameInShader) const { return glGetUniformLocation (mObjectName, _nameInShader.c_str()); }
+
+    //////////// attribute locations:
+    inline GLint getAttributeLocation    (const std::string& _nameInShader) const { return glGetAttribLocation  (mObjectName, _nameInShader.c_str()); }
+    inline void bindAttributeLocation    (const std::string& _nameInShader, GLuint _location) const { glBindAttribLocation   (mObjectName, _location, _nameInShader.c_str()); }
 
     //! Sets the attribute locations of this ShaderProgram according to the mappings specified in
     void setAttributeLocations( ConstSharedLocationMappings _locationMappings );
+    //! Get all attribute names with there locations:
+    SharedLocationMappings getAttributeLocations();
+
+    //////////// fragdata locations:
+#if (ACGL_OPENGL_VERSION >= 30)
+    inline GLint getFragmentDataLocation (const std::string& _nameInShader) const { return glGetFragDataLocation(mObjectName, _nameInShader.c_str()); }
+    inline void bindFragmentDataLocation (const std::string& _nameInShader, GLuint _location) const { glBindFragDataLocation (mObjectName, _location, _nameInShader.c_str()); }
 
     //! Sets the fragment data locations of this ShaderProgram according to the mappings specified in
     void setFragmentDataLocations( ConstSharedLocationMappings _locationMappings );
+    //! Get all fragdata names with there locations:
+    SharedLocationMappings getFragmentDataLocations();
+#endif // OpenGL >= 3.0
+
+
+    // Matches the attribute locations of this ShaderProgram to the names of the ArrayBuffer attributes currently attached to _vao
+    //void setAttributeLocationsByVAO( ConstSharedVertexArrayObject _vao );
+    // Matches the fragment data locations of this ShaderProgram to the names of the color attachments of _fbo
+    //void setFragmentDataLocationsByFBO( ConstSharedFrameBufferObject _fbo );
 
     // ===================================================================================================== \/
     // ============================================================================================ UNIFORMS \/
diff --git a/src/ACGL/OpenGL/Objects/FrameBufferObject.cc b/src/ACGL/OpenGL/Objects/FrameBufferObject.cc
index 46697c28cb83971196e977286b45a499a935fe7d..84ad31b5d6724f39626368ce823195c515e5869c 100644
--- a/src/ACGL/OpenGL/Objects/FrameBufferObject.cc
+++ b/src/ACGL/OpenGL/Objects/FrameBufferObject.cc
@@ -8,21 +8,6 @@
 using namespace ACGL;
 using namespace ACGL::OpenGL;
 
-/*
- * We can't use the constants GL_COLOR_ATTACHMENT1 to GL_COLOR_ATTACHMENT7 here
- * because OpenGL ES does not know these yet.
- */
- GLuint FrameBufferObject::msBuffers[8] = {
-    GL_COLOR_ATTACHMENT0,
-    GL_COLOR_ATTACHMENT0+1,
-    GL_COLOR_ATTACHMENT0+2,
-    GL_COLOR_ATTACHMENT0+3,
-    GL_COLOR_ATTACHMENT0+4,
-    GL_COLOR_ATTACHMENT0+5,
-    GL_COLOR_ATTACHMENT0+6,
-    GL_COLOR_ATTACHMENT0+7};
-
-
 int_t FrameBufferObject::getColorAttachmentIndexByName(const std::string& _name) const
 {
      for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
@@ -96,132 +81,103 @@ void FrameBufferObject::validate(void) const
         Utils::error() << "FrameBufferObject validation failed: No color attachments."<< std::endl;
 }
 
-void FrameBufferObject::setAttachmentsByShaderProgram(ConstSharedShaderProgram _shaderProgram)
+bool FrameBufferObject::attachColorAttachment( const Attachment &_attachment )
 {
-    // TODO: deprecate
+    int realLocation = -1;
 
-    bool needsUpdate = false;
+    for (unsigned int i = 0; i < mColorAttachments.size(); ++i) {
+        if (mColorAttachments[i].name == _attachment.name) {
+            // replace this attachment
+            mColorAttachments[i] = _attachment;
+            realLocation = i;
+        }
+    }
+    if (realLocation == -1) {
+        // it's a new attachment
+        realLocation = mColorAttachments.size();
+        mColorAttachments.push_back(_attachment);
+    }
 
-    for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
+    // attach it to the OpenGL object:
+    bind();
+    openGLCriticalErrorOccured();
+    if (_attachment.renderBuffer) {
+        // it's a renderBuffer
+        glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + realLocation, GL_RENDERBUFFER, _attachment.renderBuffer->getObjectName() );
+    } else {
+        // it's a texture
+        glFramebufferTexture2D(    GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + realLocation, _attachment.texture->getTarget(), _attachment.texture->getObjectName(), 0 );
+        Utils::debug() << "glFramebufferTexture2D( " << _attachment.name << " to " << realLocation <<" )" << std::endl;
+    }
+    if (openGLCommonErrorOccured())
     {
-        GLint fragDataLocation = _shaderProgram->getFragmentDataLocation(mColorAttachments[i].name);
+        Utils::error() << "Attaching of render target to the FBO failed" << std::endl;
+        return false;
+    }
 
-        if(fragDataLocation != -1 // does a fragment data location by that name exist in the ShaderProgram?
-        && fragDataLocation != mColorAttachmentIndices[mColorAttachments[i].name])  // does it match the index of the color attachment?
-        {
-            mColorAttachmentIndices[mColorAttachments[i].name] = fragDataLocation;
+    remapAttachments();
+    return true;
+}
 
-            needsUpdate = true;
-        }
-    }
+void FrameBufferObject::remapAttachments()
+{
+    // max color attachments: 8, TODO
+    const int maxColorBuffers = 8;
+    GLenum bufferMappings[maxColorBuffers];
+    unsigned int attachments = std::min( maxColorBuffers, (int) mColorAttachments.size() );
 
-    if(needsUpdate)
-    {
-        bind();
+    for (unsigned int i = 0; i < maxColorBuffers; ++i) {
+        bufferMappings[i] = GL_NONE;
+    }
+    for (unsigned int i = 0; i < attachments; ++i) {
+        bufferMappings[ mColorAttachments[i].location ] = GL_COLOR_ATTACHMENT0 + i;
+    }
 
-        for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
-        {
-            if(mColorAttachments[i].texture)
-                glFramebufferTexture2D(
-                    GL_FRAMEBUFFER,
-                    GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[mColorAttachments[i].name],
-                    mColorAttachments[i].texture->getTarget(),
-                    mColorAttachments[i].texture->getObjectName(),
-                    0
-                );
-            if(mColorAttachments[i].renderBuffer)
-                glFramebufferRenderbuffer(
-                    GL_FRAMEBUFFER,
-                    GL_COLOR_ATTACHMENT0 + mColorAttachmentIndices[mColorAttachments[i].name],
-                    GL_RENDERBUFFER,
-                    mColorAttachments[i].renderBuffer->getObjectName()
-                );
+    // debug:
+    Utils::message() << "remapAttachments: " << std::endl;
+    for (unsigned int i = 0; i < maxColorBuffers; ++i) {
+        if (bufferMappings[i] == GL_NONE) {
+            Utils::debug() << "bufferMappings["<<i<<"] GL_NONE" << std::endl;
+        } else {
+            Utils::debug() << "bufferMappings["<<i<<"] "<< bufferMappings[i]-GL_COLOR_ATTACHMENT0 << std::endl;
         }
     }
+    // end debug
+
 
-    openGLRareError();
+    bind(); // glDrawBuffers will get part of the FBO state!
+    glDrawBuffers( maxColorBuffers, bufferMappings );
 }
 
+
 void FrameBufferObject::setAttachmentLocations(ConstSharedLocationMappings _locationMappings)
 {
     bool needsUpdate = false;
 
-    // First, erase all existing frag data location mappings that coincide with names specified in _locationMappings
     for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
     {
         int_t location = _locationMappings->getLocation(mColorAttachments[i].name);
 
-        if(location != -1) // is a mapping by that name specified?
+        if (location != -1) // is a mapping by that name specified?
         {
-            // remove previous frag data location pointing to this color attachment
-            mFragDataLocationIndices.erase(i);
-            //ACGL::Utils::debug() << "Dropping attachment for " << mColorAttachments[i].name << " (index " << i << ")" << std::endl;
-
+            mColorAttachments[i].location = location;
             needsUpdate = true;
         }
     }
 
-    // Then, wire up the new mappings
-    for(AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
-    {
-        int_t location = _locationMappings->getLocation(mColorAttachments[i].name);
-
-        //ACGL::Utils::debug() << "Color attachment " << mColorAttachments[i].name << " (index " << i << ") should be mapped to frag data location " << location;
-        //ACGL::Utils::debug() << ". Currently mapped to: " << mFragDataLocationIndices[location] << std::endl;
-
-        if(location != -1) // is a mapping by that name specified?
-        {
-            //ACGL::Utils::debug() << "Attaching frag data location " << location << " to color attachment " << i << std::endl;
-            mFragDataLocationIndices[location] = i;
-        }
-    }
-
-    if(needsUpdate)
-    {
-        updateDrawBuffers();
-    }
+    if(needsUpdate) remapAttachments();
 }
 
-void FrameBufferObject::updateDrawBuffers()
-{
-    // No fragment data mappings set up? -> Nothing to do
-    if(mFragDataLocationIndices.size() == 0)
-    {
-        return;
-    }
 
-    // The (temporary) buffer mapping table must be large enough to contain all mapped frag data locations
-    GLint maxDrawBuffers; glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); // TODO: clever caching?
-    GLsizei numBuffers = std::min(mFragDataLocationIndices.rbegin()->first + 1, maxDrawBuffers);
+SharedLocationMappings FrameBufferObject::getAttachmentLocations()
+{
+    SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
 
-    GLenum* buffers = new GLenum[numBuffers];
-    for(GLsizei i = 0; i < numBuffers; ++i)
+    for (AttachmentVec::size_type i = 0; i < mColorAttachments.size(); i++)
     {
-        // frag data mapping for this index exists?
-        if(mFragDataLocationIndices.count(i) > 0)
-        {
-            // map the frag data location to the given color attachment
-            buffers[i] = GL_COLOR_ATTACHMENT0 + mFragDataLocationIndices[i];
-            //ACGL::Utils::debug() << "mFragDataLocationIndices[" << i << "] = " << mFragDataLocationIndices[i] << std::endl;
-        }
-        else
-        {
-            buffers[i] = GL_NONE;
-        }
+        locationMap->setLocation( mColorAttachments[i].name, mColorAttachments[i].location );
+        //ACGL::Utils::debug() << "locationMap->setLocation( "<<mColorAttachments[i].name<<", "<<mColorAttachments[i].location<<" );"<<std::endl;
     }
 
-    // TODO: remove debug output
-//    ACGL::Utils::debug() << "Uploading mapping:";
-//    for(int i = 0; i < numBuffers; ++i) {
-//        ACGL::Utils::debug() << " " << buffers[i];
-//    }
-//    ACGL::Utils::debug() << std::endl;
-
-    // upload the new mapping
-    bind();
-    glDrawBuffers(numBuffers, buffers);
-
-    delete[] buffers;
-
-    openGLRareError();
+    return locationMap;
 }
diff --git a/src/ACGL/OpenGL/Objects/ShaderProgram.cc b/src/ACGL/OpenGL/Objects/ShaderProgram.cc
index 02e39ee0f2a2cd123ed6705e7722da896860b286..744a6a746036638223acec1729401dd06d2c4a99 100644
--- a/src/ACGL/OpenGL/Objects/ShaderProgram.cc
+++ b/src/ACGL/OpenGL/Objects/ShaderProgram.cc
@@ -94,10 +94,13 @@ void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locati
         // find out whether a fragment data location with a matching name exists in this shader
         GLint fragmentDataLocation = getFragmentDataLocation((*it).first);
 
+        //ACGL::Utils::debug() << "test ("<<(*it).first<<", "<<(*it).second<<"); loc:"<<fragmentDataLocation<<std::endl;
+
         if (             fragmentDataLocation  != -1            // fragment data location with that name exists?
             && ((GLuint) fragmentDataLocation) != (*it).second) // fragment data location with that name not already bound correctly?
         {
             bindFragmentDataLocation((*it).first, (*it).second);
+            ACGL::Utils::debug() << "bindFragmentDataLocation("<<(*it).first<<", "<<(*it).second<<");"<<std::endl;
             needsRelink = true;
         }
     }
@@ -110,6 +113,47 @@ void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locati
     }
 }
 
+SharedLocationMappings ShaderProgram::getAttributeLocations()
+{
+    SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
+
+    // query the number of _active_ attributes:
+    GLint attributeCount;
+    glGetProgramiv( mObjectName, GL_ACTIVE_ATTRIBUTES, &attributeCount );
+    if (attributeCount == 0) return locationMap;
+
+    // reserve a string long enought for the longest name:
+    GLint longestAttributeName;
+    glGetProgramiv( mObjectName, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,  &longestAttributeName );
+    char *name = new char[longestAttributeName+1];
+
+    // get the name and location of each active attribute:
+    for (int i = 0; i < attributeCount; ++i) {
+        GLenum  type;
+        GLint   size;
+        GLsizei length;
+        glGetActiveAttrib( mObjectName, i, longestAttributeName, &length, &size, &type, name );
+        name[ length+1 ] = 0; // null terminate
+
+        GLint attribLocation = glGetAttribLocation( mObjectName, name );
+
+        //ACGL::Utils::debug() << "found attrib "  << name << " at " << attribLocation << std::endl;
+
+        locationMap->setLocation( std::string(name), (GLuint) attribLocation );
+    }
+
+    delete name;
+    return locationMap;
+}
+
+SharedLocationMappings ShaderProgram::getFragmentDataLocations()
+{
+    SharedLocationMappings locationMap = SharedLocationMappings( new LocationMappings() );
+
+    ACGL::Utils::error() << " ShaderProgram::getFragmentDataLocations is not implemented -> missing OpenGL API" << std::endl;
+
+    return locationMap;
+}
 
 
 /*