diff --git a/include/ACGL/OpenGL/Objects/ArrayBuffer.hh b/include/ACGL/OpenGL/Objects/ArrayBuffer.hh index 1f9a7dd2cddc0d7fa780ba3f181c742de9b0bb5b..5f5ef85eca1c0481645445353362318ec780dd4b 100644 --- a/include/ACGL/OpenGL/Objects/ArrayBuffer.hh +++ b/include/ACGL/OpenGL/Objects/ArrayBuffer.hh @@ -24,6 +24,33 @@ * itself are called ArrayBuffer and ElementArrayBuffer. */ +/*************************************************************************************************************** + * Attributes: + ************* + * + * _type is the GL type + * _size the number of elements in this attribute (1..4) + * _normalized is the attribute normalization for int types + * + * Want to add tightly packed attributes in order? + * -> use defineAttribute() + * + * Want to add attributes with individual padding in order? + * -> use defineAttributeWithPadding() + * + * Want to add attributes out-of-order? + * -> use defineAttributeWithOffset() + * + * The stride size gets always set to the minimal stride size that covers all defined attributes (/w padding). + * All define methods can get mixed! + * + * + * ab->defineAttribute( "pos", GL_FLOAT, 3 ); // stride: 12 bytes + * ab->defineAttributeWithPadding( "color", GL_CHAR, 3, 1 ); // stride: 12 + 3 + 1 = 16 bytes + * ab->defineAttributeWithOffset( "colorNorm", GL_CHAR, 3, 12, GL_TRUE ); // stride is still 16 as 12+3 <= 16! + * + **************************************************************************************************************/ + #include <ACGL/ACGL.hh> #include <ACGL/Base/Macros.hh> @@ -49,9 +76,9 @@ public: { std::string name; // human readable name, can be used to match the attribute to shader programs GLenum type; // GL_FLOAT, GL_UNSIGNED_BYTE etc. - GLint size; // #elements per attribute + GLint size; // #elements per attribute, size in bytes would be: size*sizeof(type) GLuint offset; // offset in bytes into the array - GLboolean normalized; // int types can get normalzed to 0..1 / -1..1 by GL + GLboolean normalized; // int types can get normalzed to 0..1 / -1..1 by GL, useful e.g. for colors }; // ===================================================================================================== \/ @@ -80,39 +107,20 @@ public: // ============================================================================================ GETTERS \/ // ==================================================================================================== \/ public: + + //! often the number of vertices: inline GLsizei getElements (void) const { return mSize/mStride; } + + //! size in bytes of all attributes that make up one element (vertex): inline GLsizei getStride (void) const { return mStride; } + + //! Returns the definitions of the attributes: inline const AttributeVec& getAttributes (void) const { return mAttributes; } // ==================================================================================================== \/ // ============================================================================================ METHODS \/ // ==================================================================================================== \/ public: - //int_t getAttributeIndexByName(const std::string& _nameInArray) const; - - /* Attributes: - * - * _type is the GL type - * _size the number of elements in this attribute (1..4) - * _normalized is the attribute normalization for int types - * - * Want to add tightly packed attributes in order? - * -> use defineAttribute() - * - * Want to add attributes with individual padding in order? - * -> use defineAttributeWithPadding() - * - * Want to add attributes out-of-order? - * -> use defineAttributeWithOffset() - * - * The stride size gets always set to the minimal stride size that covers all defined attributes (/w padding). - * All define methods can get mixed! - * - * - * ab->defineAttribute( "pos", GL_FLOAT, 3 ); // stride: 12 bytes - * ab->defineAttributeWithPadding( "color", GL_CHAR, 3, 1 ); // stride: 12 + 3 + 1 = 16 bytes - * ab->defineAttributeWithOffset( "colorNorm", GL_CHAR, 3, 12, GL_TRUE ); // stride is still 16 as 12+3 <= 16! - */ //! Adds the attribute at the end of the existing attributes, stride gets computed automatically void defineAttribute( const std::string& _name, @@ -121,13 +129,12 @@ public: GLboolean _normalized = GL_FALSE) { GLuint offset = mStride; - Attribute attribute = { _name, _type, _size, offset, _normalized }; defineAttribute(attribute); } //! Adds the attribute at the end of the existing attributes, stride gets computed automatically - //! + extra padding in bytes + //! + extra padding in bytes at the end void defineAttributeWithPadding( const std::string& _name, GLenum _type, @@ -135,7 +142,8 @@ public: GLuint _padding, GLboolean _normalized = GL_FALSE) { - Attribute attribute = { _name, _type, _size, (GLuint)mStride, _normalized }; + GLuint offset = mStride; + Attribute attribute = { _name, _type, _size, offset, _normalized }; defineAttribute(attribute); // defineAttribute will shift the mStride to the end of this attribute, so we only have to // add the explicit padding: @@ -143,7 +151,8 @@ public: } //! Adds an attribute defined by an offset: this way an attribute can get added at arbitrary - //! locations in the stride. If it's added at the end, the stride gets resized. + //! locations in the stride. If it's added at the end, the stride gets resized. This way attributes can even + //! overlap, hope you know what you're doing... void defineAttributeWithOffset( const std::string& _name, GLenum _type, @@ -159,8 +168,8 @@ public: void defineAttribute( const Attribute &_attribute ) { // this way attribute definitions don't have to be in order! - mStride = std::max( (GLsizei)_attribute.offset + getGLTypeSize(_attribute.type)*_attribute.size, - mStride); + GLsizei attributeWidth = getGLTypeSize(_attribute.type)*_attribute.size; // in bytes + mStride = std::max( (GLsizei)_attribute.offset + attributeWidth, mStride); mAttributes.push_back( _attribute ); } diff --git a/include/ACGL/OpenGL/Objects/Buffer.hh b/include/ACGL/OpenGL/Objects/Buffer.hh index 63ad3e1f65b5ea4c1de8d7092b7226ad1cc43f14..25ce2a23f35bbe3bdab85ccc8e13254cf984085e 100644 --- a/include/ACGL/OpenGL/Objects/Buffer.hh +++ b/include/ACGL/OpenGL/Objects/Buffer.hh @@ -31,7 +31,7 @@ namespace ACGL{ namespace OpenGL{ -/* +/** * A minimal(!) wrapper to allow multiple Buffer objects pointing to the same * OpenGL resource (like an ArrayBuffer and a TransformFeedbackBuffer). * @@ -39,6 +39,7 @@ namespace OpenGL{ * below to allow a unified API. */ class BufferObject { + ACGL_NOT_COPYABLE(BufferObject) public: BufferObject() { diff --git a/include/ACGL/OpenGL/Objects/ElementArrayBuffer.hh b/include/ACGL/OpenGL/Objects/ElementArrayBuffer.hh index b20fe8126676a54cc1d7f76720daed6d6a4bc3bd..86f1f66cdd28105d34929ba5746b944f17e2b61b 100644 --- a/include/ACGL/OpenGL/Objects/ElementArrayBuffer.hh +++ b/include/ACGL/OpenGL/Objects/ElementArrayBuffer.hh @@ -62,15 +62,16 @@ public: mType = _type; } + //! Returns the number of indices: + GLuint getElements() { + return getSize() / getGLTypeSize(mType); + } + //! Overloaded from the base class to _prevent_ redefining of the binding target! (see Buffer) inline void setTarget( GLenum ) { ACGL::Utils::error() << "DON'T redefine the target binding point of an ElementArrayBuffer" << std::endl; } - GLuint getElements() { - return getSize() / getGLTypeSize(mType); - } - // =================================================================================================== \/ // ============================================================================================ FIELDS \/ // =================================================================================================== \/ diff --git a/include/ACGL/OpenGL/Objects/FrameBufferObject.hh b/include/ACGL/OpenGL/Objects/FrameBufferObject.hh index 47de2190a0c18b5aaede8353233e3ec1da5f2854..1085e78e153b9bac622134dc096324f73644f983 100644 --- a/include/ACGL/OpenGL/Objects/FrameBufferObject.hh +++ b/include/ACGL/OpenGL/Objects/FrameBufferObject.hh @@ -140,15 +140,7 @@ public: openGLRareError(); }*/ - inline bool isFrameBufferObjectComplete(void) const - { - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - Utils::error() << "Failed to make complete FrameBufferObject object: " << (glCheckFramebufferStatus(GL_FRAMEBUFFER)) << std::endl; - return false; - } - return true; - } + bool isFrameBufferObjectComplete() const; inline bool attachColorRenderBuffer(const std::string _name, const ConstSharedRenderBuffer& _renderBuffer) { diff --git a/include/ACGL/OpenGL/Objects/LocationMappings.hh b/include/ACGL/OpenGL/Objects/LocationMappings.hh index fc8d9f45f076188a4e070e211c27dcc6ec8bd06f..0e7c69634b17759f00b9d86a214e84c661b69116 100644 --- a/include/ACGL/OpenGL/Objects/LocationMappings.hh +++ b/include/ACGL/OpenGL/Objects/LocationMappings.hh @@ -6,24 +6,39 @@ #ifndef ACGL_OPENGL_OBJECTS_LOCATIONMAPPINGS_HH #define ACGL_OPENGL_OBJECTS_LOCATIONMAPPINGS_HH +/* + * LocationMappings is a map from strings to GLuints that stores the mappings from + * + * attribute names to attribute locations + * or + * fragment outputs to fragdata locations + * + * A mapping like this can be used to init all mappings of multiple ShaderProgram + * in the same way to they can be used with the same VAOs or FBOs, similar, these + * mapping objects can be used to configute VAOs and FBOs! + * + * To fully automate the mappings in a program the creation of these mappings can + * be done automatically by parsing shader sources, querying locations and names from + * ShaderPrograms or any other way that best suits the use case of the application. + */ + #include <map> #include <string> #include <ACGL/ACGL.hh> #include <ACGL/Base/Macros.hh> +#include <ACGL/OpenGL/GL.hh> namespace ACGL{ namespace OpenGL{ class LocationMappings { - ACGL_NOT_COPYABLE(LocationMappings) - // ===================================================================================================== \/ // ============================================================================================ TYPEDEFS \/ // ===================================================================================================== \/ public: - typedef std::map< std::string, int_t > LocationMap; + typedef std::map< std::string, GLuint > LocationMap; // ========================================================================================================= \/ // ============================================================================================ CONSTRUCTORS \/ @@ -40,11 +55,12 @@ public: // ============================================================================================ GETTERS \/ // ==================================================================================================== \/ public: - inline int_t getLocation(const std::string& _name) const + //! Returns the stored location for a given name or -1 if the name could not get found (similar to how GL behaves) + GLint getLocation(const std::string& _name) const { if(exists(_name)) { - return mMappings.at(_name); + return (GLint) mMappings.at(_name); } else { @@ -52,15 +68,18 @@ public: } } - inline const LocationMap& getLocations() const { return mMappings; } + //! Returns the raw location map: + const LocationMap& getLocations() const { return mMappings; } // ==================================================================================================== \/ // ============================================================================================ SETTERS \/ // ==================================================================================================== \/ public: - inline void setLocation(const std::string& _name, int_t _location) + + //! Adds one location: + inline void setLocation(const std::string& _name, GLuint _location) { - if(exists(_name)) + if (exists(_name) && (mMappings[_name] != _location)) { ACGL::Utils::warning() << "LocationMappings: Overwriting location mapping for " << _name; ACGL::Utils::warning() << " (previous value: " << mMappings[_name] << ", new value: " << _location<< ")" << std::endl; diff --git a/include/ACGL/OpenGL/Objects/ShaderProgram.hh b/include/ACGL/OpenGL/Objects/ShaderProgram.hh index 9a90e5f08f3f003026726547467af27e9a793585..e1dd512fea3bcd4651416c8f84b642247f3c6079 100644 --- a/include/ACGL/OpenGL/Objects/ShaderProgram.hh +++ b/include/ACGL/OpenGL/Objects/ShaderProgram.hh @@ -46,7 +46,6 @@ #include <ACGL/OpenGL/GL.hh> #include <ACGL/OpenGL/Objects/Shader.hh> #include <ACGL/OpenGL/Objects/Texture.hh> -//#include <ACGL/OpenGL/Objects/FrameBufferObject.hh> #include <ACGL/OpenGL/Objects/LocationMappings.hh> #include <ACGL/Math/Math.hh> @@ -55,11 +54,11 @@ namespace ACGL{ namespace OpenGL{ -class VertexArrayObject; -ACGL_SHARED_TYPEDEF(VertexArrayObject) +//class VertexArrayObject; +//ACGL_SHARED_TYPEDEF(VertexArrayObject) -class FrameBufferObject; -ACGL_SHARED_TYPEDEF(FrameBufferObject) +//class FrameBufferObject; +//ACGL_SHARED_TYPEDEF(FrameBufferObject) class ShaderProgram { @@ -123,11 +122,10 @@ public: // ============================================================================================= METHODS \/ // ===================================================================================================== \/ 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 ); + // 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 ); //! Sets the attribute locations of this ShaderProgram according to the mappings specified in void setAttributeLocations( ConstSharedLocationMappings _locationMappings ); @@ -245,9 +243,22 @@ public: inline void setProgramUniform (GLint _location, const glm::dmat4& _v, GLboolean _transpose = GL_FALSE) const { glProgramUniformMatrix4dv (mObjectName, _location, 1, _transpose, glm::value_ptr(_v)); } #endif // OpenGL >= 4.0 - // texture - inline void setTexture (GLint _location, const ConstSharedTexture& _texture, GLenum _unit = 0) const { glUniform1i(_location, _unit); _texture->bind(_unit); } - inline void setProgramTexture (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLenum _unit = 0) const { setProgramUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); } + //! sets a texture uniform to a given texture unit and also binds the texture to the same unit + inline void setTexture (GLint _location, const ConstSharedTexture& _texture, GLenum _unit) const { glUniform1i(_location, _unit); _texture->bind(_unit); } + inline void setTexture (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLenum _unit) const { setUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); } + inline void setProgramTexture (GLint _location, const ConstSharedTexture& _texture, GLenum _unit) const { glProgramUniform1i(mObjectName, _location, _unit); _texture->bind(_unit); } + inline void setProgramTexture (const std::string& _nameInShader, const ConstSharedTexture& _texture, GLenum _unit) const { setProgramUniform( getUniformLocation(_nameInShader), (GLint) _unit); _texture->bind(_unit); } + + //! set the texture to the texture unit the uniform is set to. + //! Note: it is not guaranteed that all uniforms for textures are set to unique samplers by default after linking! + void setTexture( const std::string& _nameInShader, const ConstSharedTexture& _texture ) { + GLint unit; + GLint uniformLocation = getUniformLocation(_nameInShader); + if ( uniformLocation != -1 ) { + glGetUniformiv( mObjectName, uniformLocation, &unit ); + _texture->bind( unit ); + } + } // ======================================================================================================= \/ // ============================================================================================ HIGH LEVEL \/ @@ -295,9 +306,6 @@ public: setProgramUniform( getUniformLocation(_nameInShader), _v, _transpose); } - 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 0cfa7c39a2577a921e296521a5d3b2826c05541a..67f0aef584d2ad8aa6ee084e72743b90b6e42d23 100755 --- a/include/ACGL/OpenGL/Objects/VertexArrayObject.hh +++ b/include/ACGL/OpenGL/Objects/VertexArrayObject.hh @@ -253,6 +253,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 SharedShaderProgram &_shaderProgram ) { // TODO: deprecate @@ -296,82 +297,19 @@ public: disable(); } - } + }*/ /** - * 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. + * Query the attribute locations based on the attribute names in the ArrayBuffers. + * If they match, use the location reported from _locationMappings. */ - void setAttributeLocations( ConstSharedLocationMappings _locationMappings ) - { - bool fullUpdateNeeded = false; - - 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 mappings: attribute " << attributeName << " not specified" << std::endl; - continue; // try to match as much as possible - } - - if(mAttributes[i].location != location) - { - mAttributes[i].location = location; - fullUpdateNeeded = true; - } - } - - // 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) - { - enable(); - - // disable all attributes - GLint maxAttributes; - glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &maxAttributes ); - for (GLint i = 0; i < maxAttributes; ++i) - glDisableVertexAttribArray( i ); - - // set all attributes: - for (uint32_t i = 0; i < mAttributes.size(); ++i) - { - setAttributePointer(mAttributes[i]); - } - - disable(); - } - } + void setAttributeLocations( ConstSharedLocationMappings _locationMappings ); private: //! Sets the vertex attribute pointer for the current VAO according to the specified attribute data //! Note: expects that this VAO is currently bound //! Note: will bind the ArrayBuffer referenced by _attribute.arrayBuffer - void setAttributePointer(const Attribute& _attribute) - { - 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(); - - ArrayBuffer::Attribute arrayBufferAttribute = arrayBuffer->getAttributes()[_attribute.attributeID]; - glVertexAttribPointer(_attribute.location, - arrayBufferAttribute.size, - arrayBufferAttribute.type, - arrayBufferAttribute.normalized, - arrayBuffer->getStride(), - reinterpret_cast<GLvoid*>(arrayBufferAttribute.offset) - ); - glEnableVertexAttribArray(_attribute.location); - } + void setAttributePointer(const Attribute& _attribute); // ===================================================================================================== \/ // ============================================================================================ WRAPPERS \/ @@ -383,39 +321,17 @@ public: glBindVertexArray( mObjectName ); } - //! Bind this VAO and remember the previously bound VAO - //! Note: every call to this method must be paired with a corresponding call to disable() - inline void enable(void) const - { - // remember old VAO - glGetIntegerv( GL_VERTEX_ARRAY_BINDING, &sPreviousVAOName ); - bind(); - } - - //! Bind the VAO that was bound before the most recent enable() call - inline void disable(void) const - { - glBindVertexArray(sPreviousVAOName); - } - //! Nothing has to be prepared for a render call - inline void render (void) const + inline void render (void) { enable(); draw(); disable(); } - //! Will select the matching draw call. Remember to enable first! + //! Will select the matching draw call. Remember to bind() first! void draw(void) const { - // TODO: fail silently? - if(mAttributes.empty()) - { - ACGL::Utils::error() << "cannot draw VAO with no attributes attached" << std::endl; - return; - } - if(mpElementArrayBuffer) drawElements(); else @@ -447,20 +363,39 @@ public: //! Draws all elements inline void drawArrays(void) const { + if(mAttributes.empty()) + { + ACGL::Utils::error() << "cannot draw VAO with no attributes attached" << std::endl; + return; + } drawArrays(mAttributes[0].arrayBuffer->getElements()); } // =================================================================================================== \/ // ============================================================================================ FIELDS \/ // =================================================================================================== \/ -protected: +private: GLuint mObjectName; // OpenGL object name SharedElementArrayBuffer mpElementArrayBuffer; // optional EAB AttributeVec mAttributes; // vertex attributes GLenum mMode; // primitive type to render (e.g. GL_TRIANGLES) -private: - static GLint sPreviousVAOName; // the VAO that was bound before the last enable() call + //! Bind this VAO and remember the previously bound VAO + //! Note: every call to this method must be paired with a corresponding call to disable() + inline void enable(void) + { + // remember old VAO + glGetIntegerv( GL_VERTEX_ARRAY_BINDING, &mPreviousVAOName ); + if (mObjectName != (GLuint)mPreviousVAOName) bind(); + } + + //! Bind the VAO that was bound before the most recent enable() call + inline void disable(void) + { + if (mObjectName != (GLuint)mPreviousVAOName) glBindVertexArray((GLuint)mPreviousVAOName); + } + + GLint mPreviousVAOName; // the VAO that was bound before the last enable() call }; ACGL_SHARED_TYPEDEF(VertexArrayObject) diff --git a/src/ACGL/OpenGL/Objects/FrameBufferObject.cc b/src/ACGL/OpenGL/Objects/FrameBufferObject.cc index 846c298440e8fc31c334fb84aaaf3084d0293558..46697c28cb83971196e977286b45a499a935fe7d 100644 --- a/src/ACGL/OpenGL/Objects/FrameBufferObject.cc +++ b/src/ACGL/OpenGL/Objects/FrameBufferObject.cc @@ -34,8 +34,35 @@ int_t FrameBufferObject::getColorAttachmentIndexByName(const std::string& _name) return -1; } +bool FrameBufferObject::isFrameBufferObjectComplete() const +{ + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + { + Utils::error() << "Failed to make complete FrameBufferObject object: "; + if (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { + Utils::error() << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; + } else if (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) { + Utils::error() << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; + } else if (status == GL_FRAMEBUFFER_UNSUPPORTED) { + Utils::error() << "GL_FRAMEBUFFER_UNSUPPORTED"; + } else if (status == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE) { + Utils::error() << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; + } else { + Utils::error() << status; + } + Utils::error() << std::endl; + return false; + } + return true; +} + void FrameBufferObject::validate(void) const { + // if OpenGL says were ok, return + if (isFrameBufferObjectComplete()) return; + + // the above call will create some output, but let's try to get more infos: if(mColorAttachments.size() > 0) { int width = -1; diff --git a/src/ACGL/OpenGL/Objects/RenderObject.cc b/src/ACGL/OpenGL/Objects/RenderObject.cc index df9833936d61a70b4d3c7f3c01506bdee82a9395..a1d4b16825598be0090d4c3f91477d90b968861f 100644 --- a/src/ACGL/OpenGL/Objects/RenderObject.cc +++ b/src/ACGL/OpenGL/Objects/RenderObject.cc @@ -79,7 +79,7 @@ void RenderObject::enableVertexArrayObject() const { if(mpVertexArrayObject) { - mpVertexArrayObject->enable(); + mpVertexArrayObject->bind(); } else { diff --git a/src/ACGL/OpenGL/Objects/ShaderProgram.cc b/src/ACGL/OpenGL/Objects/ShaderProgram.cc index 3821e1c3d640b325b62f3649a808923af181d47d..02e39ee0f2a2cd123ed6705e7722da896860b286 100644 --- a/src/ACGL/OpenGL/Objects/ShaderProgram.cc +++ b/src/ACGL/OpenGL/Objects/ShaderProgram.cc @@ -50,29 +50,24 @@ bool ShaderProgram::link() const return true; } -void ShaderProgram::setAttributeLocationsByVAO(ConstSharedVertexArrayObject _vao) +void ShaderProgram::setAttributeLocations(ConstSharedLocationMappings _locationMappings) { - // TODO: deprecate - 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; + // search through all attributes: + LocationMappings::LocationMap locations = _locationMappings->getLocations(); - // find the name of the current attribute in its ArrayBuffer - std::string arrayBufferAttributeName = vaoAttributes[i].arrayBuffer->getAttributes()[vaoAttributes[i].attributeID].name; + for(LocationMappings::LocationMap::iterator it = locations.begin(); + it != locations.end(); + ++it) + { + // find out whether a fragment data location with a matching name exists in this shader + GLint attributeLocation = getAttributeLocation((*it).first); - // 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? + if ( attributeLocation != -1 // attributeLocation with that name exists? + && ((GLuint)attributeLocation) != (*it).second) // attributeLocation with that name not already bound correctly? { - bindAttributeLocation(arrayBufferAttributeName, vaoAttributes[i].location); - + bindAttributeLocation((*it).first, (*it).second); needsRelink = true; } } @@ -85,23 +80,24 @@ void ShaderProgram::setAttributeLocationsByVAO(ConstSharedVertexArrayObject _vao } } -void ShaderProgram::setFragmentDataLocationsByFBO(ConstSharedFrameBufferObject _fbo) +void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locationMappings) { - // TODO: deprecate - bool needsRelink = false; - // search through all color attachments of _fbo - FrameBufferObject::AttachmentVec fboAttachments = _fbo->getColorAttachments(); - for(FrameBufferObject::AttachmentVec::size_type i = 0; i < fboAttachments.size(); ++i) + // search through all color attachments: + LocationMappings::LocationMap locations = _locationMappings->getLocations(); + + for(LocationMappings::LocationMap::iterator it = locations.begin(); + it != locations.end(); + ++it) { // find out whether a fragment data location with a matching name exists in this shader - GLint fragmentDataLocation = getFragmentDataLocation(fboAttachments[i].name); - if ( fragmentDataLocation != -1 // fragment data location with that name exists? - && fragmentDataLocation != (GLint) i) // fragment data location with that name not already bound correctly? - { - bindFragmentDataLocation(fboAttachments[i].name, i); + GLint fragmentDataLocation = getFragmentDataLocation((*it).first); + 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); needsRelink = true; } } @@ -114,24 +110,31 @@ void ShaderProgram::setFragmentDataLocationsByFBO(ConstSharedFrameBufferObject _ } } -void ShaderProgram::setAttributeLocations(ConstSharedLocationMappings _locationMappings) + + +/* +void ShaderProgram::setAttributeLocationsByVAO(ConstSharedVertexArrayObject _vao) { - bool needsRelink = false; + // TODO: deprecate - // search through all color attachments of _fbo - LocationMappings::LocationMap locations = _locationMappings->getLocations(); + bool needsRelink = false; - for(LocationMappings::LocationMap::iterator it = locations.begin(); - it != locations.end(); - ++it) + // search through all attributes of _vao + VertexArrayObject::AttributeVec vaoAttributes = _vao->getAttributes(); + for(VertexArrayObject::AttributeVec::size_type i = 0; i < vaoAttributes.size(); ++i) { - // find out whether a fragment data location with a matching name exists in this shader - GLint fragmentDataLocation = getAttributeLocation((*it).first); + if(vaoAttributes[i].location == -1) + continue; - if(fragmentDataLocation != -1 // fragment data location with that name exists? - && fragmentDataLocation != (*it).second) // fragment data location with that name not already bound correctly? + // 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((*it).first, (*it).second); + bindAttributeLocation(arrayBufferAttributeName, vaoAttributes[i].location); needsRelink = true; } @@ -143,26 +146,24 @@ void ShaderProgram::setAttributeLocations(ConstSharedLocationMappings _locationM link(); openGLRareError(); } -} - -void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locationMappings) +}*/ +/* +void ShaderProgram::setFragmentDataLocationsByFBO(ConstSharedFrameBufferObject _fbo) { + // TODO: deprecate + bool needsRelink = false; // search through all color attachments of _fbo - LocationMappings::LocationMap locations = _locationMappings->getLocations(); - - for(LocationMappings::LocationMap::iterator it = locations.begin(); - it != locations.end(); - ++it) + FrameBufferObject::AttachmentVec fboAttachments = _fbo->getColorAttachments(); + for(FrameBufferObject::AttachmentVec::size_type i = 0; i < fboAttachments.size(); ++i) { // find out whether a fragment data location with a matching name exists in this shader - GLint fragmentDataLocation = getFragmentDataLocation((*it).first); - - if(fragmentDataLocation != -1 // fragment data location with that name exists? - && fragmentDataLocation != (*it).second) // fragment data location with that name not already bound correctly? + GLint fragmentDataLocation = getFragmentDataLocation(fboAttachments[i].name); + if ( fragmentDataLocation != -1 // fragment data location with that name exists? + && fragmentDataLocation != (GLint) i) // fragment data location with that name not already bound correctly? { - bindFragmentDataLocation((*it).first, (*it).second); + bindFragmentDataLocation(fboAttachments[i].name, i); needsRelink = true; } @@ -174,4 +175,4 @@ void ShaderProgram::setFragmentDataLocations(ConstSharedLocationMappings _locati link(); openGLRareError(); } -} +}*/ diff --git a/src/ACGL/OpenGL/Objects/VertexArrayObject.cc b/src/ACGL/OpenGL/Objects/VertexArrayObject.cc index 5c4ad9fc26189dd0ff177b29515fcd5542a41e4e..df72ae3dd4319e3b67afd92e680d3320dfeefd9b 100755 --- a/src/ACGL/OpenGL/Objects/VertexArrayObject.cc +++ b/src/ACGL/OpenGL/Objects/VertexArrayObject.cc @@ -9,8 +9,6 @@ using namespace ACGL; using namespace ACGL::OpenGL; -GLint VertexArrayObject::sPreviousVAOName = 0; - bool VertexArrayObject::isValid(void) const { GLsizei elements = 0; @@ -39,4 +37,82 @@ bool VertexArrayObject::isValid(void) const return true; } + + +void VertexArrayObject::setAttributeLocations( ConstSharedLocationMappings _locationMappings ) +{ + bool fullUpdateNeeded = false; + GLint maxAttributes; + glGetIntegerv( GL_MAX_VERTEX_ATTRIBS, &maxAttributes ); + + 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; + } + } + + // 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) + { + enable(); + + // 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]); + } + + disable(); + } +} + + +void VertexArrayObject::setAttributePointer(const Attribute& _attribute) +{ + 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(); + + ArrayBuffer::Attribute arrayBufferAttribute = arrayBuffer->getAttributes()[_attribute.attributeID]; + glVertexAttribPointer(_attribute.location, + arrayBufferAttribute.size, + arrayBufferAttribute.type, + arrayBufferAttribute.normalized, + arrayBuffer->getStride(), + reinterpret_cast<GLvoid*>(arrayBufferAttribute.offset) + ); + glEnableVertexAttribArray(_attribute.location); +} + + + #endif // (ACGL_OPENGL_VERSION >= 30)