Commit 55d9f005 authored by Robert Menzel's avatar Robert Menzel
Browse files

redone VAO mappings

parent 27d91969
......@@ -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);
/*
......
......@@ -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 \/
// ==================================================================================================== \/
......
......@@ -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 \/
// =================================================================================================== \/
......
......@@ -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 \/
......
......@@ -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 )
......
......@@ -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;
}
}
......@@ -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
......@@ -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);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment