Commit 863b846e authored by Christopher Tenter's avatar Christopher Tenter
Browse files

add support for instancing from vbo via VertexDeclaration

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@20108 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 47c2e19e
...@@ -1637,7 +1637,7 @@ bool ACG::DrawMeshT<Mesh>::supportsPickingVertices_opt() ...@@ -1637,7 +1637,7 @@ bool ACG::DrawMeshT<Mesh>::supportsPickingVertices_opt()
// else // else
// pickVertexShader_ = GLSL::loadProgram("Picking/vertex.glsl", "Picking/pick_vertices_fs2.glsl"); // pickVertexShader_ = GLSL::loadProgram("Picking/vertex.glsl", "Picking/pick_vertices_fs2.glsl");
// } // }
// load from cache // load from cache
if (pickVertexMethod_ == 0) if (pickVertexMethod_ == 0)
pickVertexShader_ = ShaderCache::getInstance()->getProgram("Picking/pick_vertices_vs.glsl", "Picking/pick_vertices_fs.glsl", 0, false); pickVertexShader_ = ShaderCache::getInstance()->getProgram("Picking/pick_vertices_vs.glsl", "Picking/pick_vertices_fs.glsl", 0, false);
...@@ -2040,10 +2040,9 @@ void DrawMeshT<Mesh>::updatePickingFaces_opt(ACG::GLState& _state ) ...@@ -2040,10 +2040,9 @@ void DrawMeshT<Mesh>::updatePickingFaces_opt(ACG::GLState& _state )
template <class Mesh> template <class Mesh>
bool ACG::DrawMeshT<Mesh>::supportsPickingFaces_opt() bool ACG::DrawMeshT<Mesh>::supportsPickingFaces_opt()
{ {
#ifndef GL_ARB_texture_buffer_object if (!ACG::Texture::supportsTextureBuffer())
return 0; return false;
#endif
// fetch picking shader from cache // fetch picking shader from cache
pickFaceShader_ = ShaderCache::getInstance()->getProgram("Picking/vertex.glsl", "Picking/pick_face.glsl", 0, false); pickFaceShader_ = ShaderCache::getInstance()->getProgram("Picking/vertex.glsl", "Picking/pick_face.glsl", 0, false);
...@@ -2390,27 +2389,16 @@ void ACG::DrawMeshT<Mesh>::createVertexDeclaration() ...@@ -2390,27 +2389,16 @@ void ACG::DrawMeshT<Mesh>::createVertexDeclaration()
template <class Mesh> template <class Mesh>
void ACG::DrawMeshT<Mesh>::updateEdgeHalfedgeVertexDeclarations() void ACG::DrawMeshT<Mesh>::updateEdgeHalfedgeVertexDeclarations()
{ {
VertexElement elemArrayEC[] = { {GL_FLOAT, 3, VERTEX_USAGE_POSITION, 0, 0 },
{GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, 0, 0 } };
elemArrayEC[0].pointer_ = perEdgeVertexBuffer();
elemArrayEC[1].pointer_ = perEdgeColorBuffer();
VertexElement elemArrayH = {GL_FLOAT, 3, VERTEX_USAGE_POSITION, 0, 0 };
elemArrayH.pointer_ = perHalfedgeVertexBuffer();
VertexElement elemArrayHC[] = { {GL_FLOAT, 3, VERTEX_USAGE_POSITION, 0, 0 },
{GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, 0, 0 } };
elemArrayHC[0].pointer_ = perHalfedgeVertexBuffer();
elemArrayHC[1].pointer_ = perHalfedgeColorBuffer();
vertexDeclEdgeCol_->clear(); vertexDeclEdgeCol_->clear();
vertexDeclEdgeCol_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perEdgeVertexBuffer());
vertexDeclEdgeCol_->addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, perEdgeColorBuffer());
vertexDeclHalfedgeCol_->clear(); vertexDeclHalfedgeCol_->clear();
vertexDeclHalfedgeCol_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perHalfedgeVertexBuffer());
vertexDeclHalfedgeCol_->addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, perHalfedgeColorBuffer());
vertexDeclHalfedgePos_->clear(); vertexDeclHalfedgePos_->clear();
vertexDeclHalfedgePos_->addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION, perHalfedgeVertexBuffer());
vertexDeclEdgeCol_->addElements(2, elemArrayEC);
vertexDeclHalfedgeCol_->addElements(2, elemArrayHC);
vertexDeclHalfedgePos_->addElement(&elemArrayH);
vertexDeclEdgeCol_->setVertexStride(0); vertexDeclEdgeCol_->setVertexStride(0);
vertexDeclHalfedgeCol_->setVertexStride(0); vertexDeclHalfedgeCol_->setVertexStride(0);
......
...@@ -55,6 +55,11 @@ ...@@ -55,6 +55,11 @@
namespace ACG namespace ACG
{ {
VertexElement::VertexElement()
: type_(0), numElements_(0), usage_(VERTEX_USAGE_SHADER_INPUT), shaderInputName_(0), pointer_(0), divisor_(0), vbo_(0)
{
}
void VertexElement::setByteOffset(unsigned int _offset) void VertexElement::setByteOffset(unsigned int _offset)
{ {
...@@ -106,7 +111,9 @@ void VertexDeclaration::addElement(unsigned int _type, ...@@ -106,7 +111,9 @@ void VertexDeclaration::addElement(unsigned int _type,
unsigned int _numElements, unsigned int _numElements,
VERTEX_USAGE _usage, VERTEX_USAGE _usage,
const void* _pointer, const void* _pointer,
const char* _shaderInputName) const char* _shaderInputName,
unsigned int _divisor,
unsigned int _vbo)
{ {
VertexElement* ve = new VertexElement(); VertexElement* ve = new VertexElement();
...@@ -115,6 +122,8 @@ void VertexDeclaration::addElement(unsigned int _type, ...@@ -115,6 +122,8 @@ void VertexDeclaration::addElement(unsigned int _type,
ve->usage_ = _usage; ve->usage_ = _usage;
ve->shaderInputName_ = _shaderInputName; ve->shaderInputName_ = _shaderInputName;
ve->pointer_ = _pointer; ve->pointer_ = _pointer;
ve->divisor_ = _divisor;
ve->vbo_ = _vbo;
addElement(ve); addElement(ve);
delete ve; delete ve;
...@@ -124,7 +133,9 @@ void VertexDeclaration::addElement(unsigned int _type, ...@@ -124,7 +133,9 @@ void VertexDeclaration::addElement(unsigned int _type,
unsigned int _numElements, unsigned int _numElements,
VERTEX_USAGE _usage, VERTEX_USAGE _usage,
size_t _byteOffset, size_t _byteOffset,
const char* _shaderInputName) const char* _shaderInputName,
unsigned int _divisor,
unsigned int _vbo)
{ {
VertexElement* ve = new VertexElement(); VertexElement* ve = new VertexElement();
...@@ -133,6 +144,8 @@ void VertexDeclaration::addElement(unsigned int _type, ...@@ -133,6 +144,8 @@ void VertexDeclaration::addElement(unsigned int _type,
ve->usage_ = _usage; ve->usage_ = _usage;
ve->shaderInputName_ = _shaderInputName; ve->shaderInputName_ = _shaderInputName;
ve->pointer_ = (void*)_byteOffset; ve->pointer_ = (void*)_byteOffset;
ve->divisor_ = _divisor;
ve->vbo_ = _vbo;
addElement(ve); addElement(ve);
...@@ -170,18 +183,42 @@ void VertexDeclaration::addElements(unsigned int _numElements, const VertexEleme ...@@ -170,18 +183,42 @@ void VertexDeclaration::addElements(unsigned int _numElements, const VertexEleme
const void* p; const void* p;
} lastOffset, firstOffset; } lastOffset, firstOffset;
firstOffset.p = getElement(0)->pointer_;
const VertexElement* pLastElement = getElement(n-1);
lastOffset.p = pLastElement->pointer_;
vertexStride_ = static_cast<unsigned int>(lastOffset.u + getElementSize( pLastElement ) - firstOffset.u);
std::map<unsigned int, VertexElement*> vboFirstElements;
std::map<unsigned int, VertexElement*> vboLastElements;
for (unsigned int i = 0; i < n; ++i)
{
if (vboFirstElements.find(elements_[i].vbo_) == vboFirstElements.end())
vboFirstElements[elements_[i].vbo_] = &elements_[i];
vboLastElements[elements_[i].vbo_] = &elements_[i];
}
for (std::map<unsigned int, VertexElement*>::iterator it = vboFirstElements.begin(); it != vboFirstElements.end(); ++it)
{
VertexElement* lastElement = vboLastElements[it->first];
firstOffset.p = it->second->pointer_;
lastOffset.p = lastElement->pointer_;
vertexStridesVBO_[it->first] = static_cast<unsigned int>(lastOffset.u + getElementSize( lastElement ) - firstOffset.u);
}
vertexStride_ = vertexStridesVBO_.begin()->second;
} }
} }
} }
// union instead of reinterpret_cast for cross-platform compatibility, must be global for use in std::map
union VertexDeclaration_ptr2uint
{
unsigned long u;
const void* p;
};
void VertexDeclaration::updateOffsets() void VertexDeclaration::updateOffsets()
{ {
...@@ -190,25 +227,44 @@ void VertexDeclaration::updateOffsets() ...@@ -190,25 +227,44 @@ void VertexDeclaration::updateOffsets()
if (!numElements) return; if (!numElements) return;
// union instead of reinterpret_cast for cross-platform compatibility // separate offsets for each vbo
union ptr2uint
{ std::map<unsigned int, VertexDeclaration_ptr2uint> vboOffsets;
unsigned long u; std::map<unsigned int, VertexElement*> vboPrevElements;
const void* p;
};
ptr2uint curOffset; for (unsigned int i = 0; i < numElements; ++i)
curOffset.p = elements_[0].pointer_; {
if (vboOffsets.find(elements_[i].vbo_) == vboOffsets.end())
{
vboOffsets[elements_[i].vbo_].p = elements_[i].pointer_;
vboPrevElements[elements_[i].vbo_] = &elements_[i];
}
}
for (unsigned int i = 1; i < numElements; ++i) for (unsigned int i = 0; i < numElements; ++i)
{ {
if (elements_[i].pointer_) VertexElement* el = &elements_[i];
curOffset.p = elements_[i].pointer_;
bool updateOffset = false;
if (el->pointer_)
{
vboOffsets[el->vbo_].p = el->pointer_;
vboPrevElements[el->vbo_] = el;
}
else else
curOffset.u += getElementSize(&elements_[i-1]); {
VertexElement* prevEl = vboPrevElements[el->vbo_];
if (prevEl != el)
{
updateOffset = true;
vboOffsets[el->vbo_].u += getElementSize(prevEl);
}
vboPrevElements[el->vbo_] = el;
}
elements_[i].pointer_ = curOffset.p; if (updateOffset)
el->pointer_ = vboOffsets[el->vbo_].p;
} }
} }
...@@ -282,7 +338,7 @@ unsigned int VertexDeclaration::getGLTypeSize(unsigned int _type) ...@@ -282,7 +338,7 @@ unsigned int VertexDeclaration::getGLTypeSize(unsigned int _type)
unsigned int VertexDeclaration::getElementSize(const VertexElement* _pElement) unsigned int VertexDeclaration::getElementSize(const VertexElement* _pElement)
{ {
return getGLTypeSize(_pElement->type_) * _pElement->numElements_; return _pElement ? getGLTypeSize(_pElement->type_) * _pElement->numElements_ : 0;
} }
...@@ -367,10 +423,11 @@ void VertexDeclaration::activateShaderPipeline(GLSL::Program* _prog) const ...@@ -367,10 +423,11 @@ void VertexDeclaration::activateShaderPipeline(GLSL::Program* _prog) const
// setup correct attribute locations as specified // setup correct attribute locations as specified
unsigned int numElements = getNumElements(); unsigned int numElements = getNumElements();
unsigned int vertexStride = getVertexStride();
for (unsigned int i = 0; i < numElements; ++i) for (unsigned int i = 0; i < numElements; ++i)
{ {
unsigned int vertexStride = getVertexStride(i);
const VertexElement* pElem = &elements_[i]; const VertexElement* pElem = &elements_[i];
int loc = _prog->getAttributeLocation(pElem->shaderInputName_); int loc = _prog->getAttributeLocation(pElem->shaderInputName_);
...@@ -384,9 +441,28 @@ void VertexDeclaration::activateShaderPipeline(GLSL::Program* _prog) const ...@@ -384,9 +441,28 @@ void VertexDeclaration::activateShaderPipeline(GLSL::Program* _prog) const
if (pElem->usage_ == VERTEX_USAGE_BLENDINDICES) if (pElem->usage_ == VERTEX_USAGE_BLENDINDICES)
normalizeElem = GL_FALSE; normalizeElem = GL_FALSE;
GLint curVBO = 0;
if (pElem->vbo_)
{
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &curVBO);
glBindBuffer(GL_ARRAY_BUFFER, pElem->vbo_);
}
glVertexAttribPointer(loc, pElem->numElements_, pElem->type_, normalizeElem, vertexStride, pElem->pointer_); glVertexAttribPointer(loc, pElem->numElements_, pElem->type_, normalizeElem, vertexStride, pElem->pointer_);
if (supportsInstancedArrays())
{
#ifdef GL_ARB_instanced_arrays
glVertexAttribDivisor(loc, pElem->divisor_);
#endif
}
else if (pElem->divisor_)
std::cerr << "error: VertexDeclaration::activateShaderPipeline - instanced arrays not supported by gpu!" << std::endl;
glEnableVertexAttribArray(loc); glEnableVertexAttribArray(loc);
if (curVBO)
glBindBuffer(GL_ARRAY_BUFFER, curVBO);
} }
} }
} }
...@@ -438,9 +514,13 @@ const VertexElement* VertexDeclaration::findElementByUsage(VERTEX_USAGE _usage) ...@@ -438,9 +514,13 @@ const VertexElement* VertexDeclaration::findElementByUsage(VERTEX_USAGE _usage)
} }
unsigned int VertexDeclaration::getVertexStride() const unsigned int VertexDeclaration::getVertexStride(unsigned int i) const
{ {
return vertexStride_; unsigned int vbo = getElement(i)->vbo_;
std::map<unsigned int, unsigned int>::const_iterator it = vertexStridesVBO_.find(vbo);
return (it != vertexStridesVBO_.end()) ? it->second : vertexStride_;
// return vertexStride_;
} }
...@@ -509,12 +589,28 @@ QString VertexDeclaration::toString() const ...@@ -509,12 +589,28 @@ QString VertexDeclaration::toString() const
<< ", count: " << el->numElements_ << ", count: " << el->numElements_
<< ", usage: " << usage << ", usage: " << usage
<< ", shader-input: " << el->shaderInputName_ << ", shader-input: " << el->shaderInputName_
<< ", offset: " << el->pointer_ << "]\n"; << ", offset: " << el->pointer_
<< ", divisor: " << el->divisor_
<< ", vbo: " << el->vbo_
<< ", stride: " << getVertexStride(i)
<< "]\n";
} }
return result; return result;
} }
bool VertexDeclaration::supportsInstancedArrays()
{
static int status_ = -1;
#ifdef GL_ARB_instanced_arrays
if (status_ < 0) // core in 3.3
status_ = (checkExtensionSupported("GL_ARB_instanced_arrays") || openGLVersion(3,3)) ? 1 : 0;
#endif
return status_ > 0;
}
//============================================================================= //=============================================================================
} // namespace ACG } // namespace ACG
//============================================================================= //=============================================================================
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include <map>
#include <QString> #include <QString>
#include <ACG/Config/ACGDefines.hh> #include <ACG/Config/ACGDefines.hh>
...@@ -75,11 +76,15 @@ enum VERTEX_USAGE ...@@ -75,11 +76,15 @@ enum VERTEX_USAGE
*/ */
struct ACGDLLEXPORT VertexElement struct ACGDLLEXPORT VertexElement
{ {
VertexElement();
unsigned int type_; //!< GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ... unsigned int type_; //!< GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
unsigned int numElements_; //!< how many elements of type_ unsigned int numElements_; //!< how many elements of type_
VERTEX_USAGE usage_; //!< position, normal, shader input .. VERTEX_USAGE usage_; //!< position, normal, shader input ..
const char* shaderInputName_; //!< set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically, if usage_ != VERTEX_USAGE_USER_DEFINED const char* shaderInputName_; //!< set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically, if usage_ != VERTEX_USAGE_USER_DEFINED
const void* pointer_; //!< Offset in bytes to the first instance of this element in vertex buffer; Or address to vertex data in system memory const void* pointer_; //!< Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data in system memory
unsigned int divisor_; //!< For instanced rendering: Step rate describing how many instances are drawn before advancing to the next element. Must be 0 if this element is not per instance data.
unsigned int vbo_; //!< Explicit vbo source of this element, set to 0 if the buffer bound at the time of activating the declaration should be used instead.
/*! interpret pointer_ as byte offset /*! interpret pointer_ as byte offset
*/ */
...@@ -90,21 +95,24 @@ struct ACGDLLEXPORT VertexElement ...@@ -90,21 +95,24 @@ struct ACGDLLEXPORT VertexElement
unsigned int getByteOffset() const; unsigned int getByteOffset() const;
}; };
/** \brief Class to define the layout of a vertex element /** \brief Class to define the vertex input layout
* *
* This class is used to specify how the elements (normals,positions,...) of a vertex element are setup. * This class is used to specify vertex data layout (normals,positions,...).
* *
* A vertex declaration is needed to describe the data layout of a vertex buffer: * The layout of a vertex buffer typically includes:
* - number of vertex elements * - number of vertex elements
* - element usage (position, normal, ... ) * - element usage (position, normal, ... )
* - element types (float, int, ...) * - element types (float, int, ...)
* - memory alignment * - memory alignment
* - data pointers (only in case of system memory buffers) * - data pointers (only in case of system memory buffers)
* - source vertex buffers
* - divisor (step rate) for instance data
* - vertex stride
*
* *
* Example usage: Interleaved vertex data
* *
* Example usage: * Create a vertex declaration given the following vertex data:
*
* Suppose you have an interleaved vertex buffer without memory alignment:
* \code * \code
* Vertex * Vertex
* { * {
...@@ -117,28 +125,21 @@ struct ACGDLLEXPORT VertexElement ...@@ -117,28 +125,21 @@ struct ACGDLLEXPORT VertexElement
* } * }
* \endcode * \endcode
* *
* You would create the following VertexElements: * The accompanying vertex declaration is created as follows:
* \code * \code
* VertexElement elemArray[] = { {GL_FLOAT, 4, VERTEX_USAGE_POSITION, 0, {0} }, * VertexDeclaration decl;
* {GL_FLOAT, 3, VERTEX_USAGE_NORMAL, 0, {0} }, * decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_POSITION);
* {GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD, 0, {0} }, * decl.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL);
* {GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, 0, {0} }, * decl.addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD);
* {GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, "inTangent", {0} }, * decl.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR);
* {GL_FLOAT, 2, VERTEX_USAGE_SHADER_INPUT, "inTexcoord2", {0}} * decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, 0U, "inTangent");
* }; * decl.addElement(GL_FLOAT, 2, VERTEX_USAGE_SHADER_INPUT, 0U, "inTexcoord2");
* \endcode
* *
* equivalent to
* \code
* VertexElement elemArray[] = { {GL_FLOAT, 4, VERTEX_USAGE_POSITION, 0, {0} },
* {GL_FLOAT, 3, VERTEX_USAGE_NORMAL, 0, {4*4} },
* {GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD, 0, {4*4 + 4*3} },
* {GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, 0, {4*4 + 4*3 + 4*2} },
* ..
* };
* \endcode * \endcode
* *
* in the vertex shader: * Note that the element offsets are automatically computed, but it is possible to provide them manually of course.
*
* These elements are then available in a vertex shader with the following input semantics:
* \code * \code
* in vec4 inPosition; * in vec4 inPosition;
* ... * ...
...@@ -151,38 +152,110 @@ struct ACGDLLEXPORT VertexElement ...@@ -151,38 +152,110 @@ struct ACGDLLEXPORT VertexElement
* *
* --------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------
* *
* Example use: multiple buffer source in system memory * Example usage: Multiple source buffers in system memory
*
* Suppose you have the following arrays in system memory
* *
* Given are system memory buffers as vertex data source for drawing:
* \code * \code
* float4* pVertexPositions; * float4* pVertexPositions;
* ubyte4* pVertexColors; * ubyte4* pVertexColors;
* float3* pVertexNormals; * float3* pVertexNormals;
* \endcode * \endcode
* *
* important is, that you define a vertex stride of 0 and define the data pointer in the vertex elements instead * It is important that the vertex stride is manually set to 0!! and that the element data pointers are set accordingly:
*
* The correct vertex declaration to use is:
* *
* \code * \code
* VertexElement elemArray[] = { {GL_FLOAT, 4, VERTEX_USAGE_POSITION, 0, pVertexPositions}, * VertexDeclaration decl;
* {GL_FLOAT, 3, VERTEX_USAGE_NORMAL, 0, pVertexNormals}, * decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_POSITION, pVertexPositions);
* {GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, 0, pVertexColors} * decl.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL, pVertexNormals);
* }; * decl.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, pVertexColors);
* * decl.setVertexStride(0);
* VertexDeclaration* pDecl = new VertexDeclaration();
*
* pDecl->addElements(3, elemArray);
* pDecl->setVertexStride(0);
* \endcode * \endcode
* *
*
* Note: * Note:
* - vertex stride = 0 * - vertex stride = 0
* - assign data address in vertex elements and don't change the data location later * - assign data address in vertex elements and don't change the data location later
* - order of elements is not important in this case * - order of elements is not important in this case
* - mixing interleaved vbo and system memory elements in the same declaration is forbidden
*
* ---------------------------------------------------------------------------------
*
* Example usage: Instancing from vbo
*
* Geometry instancing can be implemented in several ways:
* - compute instance transform procedurally from gl_InstanceID in shader
* - store per instance data in a texture and use vertex texture fetch via gl_InstanceID
* - store per instance data in a vbo and stream these as input to a vertex shader (ARB_instanced_arrays).
*
* The first two methods can be implemented without modifying the vertex declaration,
* so this example focuses on the last method, in which instance data is streamed from a vbo.
*
* Given a mesh with the following vertex elements:
* \code
* Vertex
* {
* float4 pos
* float3 normal
* float2 texcoord
* }
* \endcode
*
* Each instance of this mesh should have a different world transform and a different color.
* So the per instance data is:
* \code
* InstanceData
* {
* mat4 modelview
* uint color
* }
* \endcode
* *
* This per instance data is stored in a separate GL_ARRAY_BUFFER vbo.
*
* So there are two vbos involved in the draw call:
* geometryVBO - stores static Vertex data of the mesh
* instanceVBO - stores InstanceData for each instance
*
* The vertex declaration for the instanced draw call is initialized as follows:
*
* \code
* VertexDeclaration decl;
* decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_POSITION, 0U, 0, 0, geometryVBO.id()); // mesh vertex data layout
* decl.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL, 0U, 0, 0, geometryVBO.id());
* decl.addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD, 0U, 0, 0, geometryVBO.id());
*
* decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, 0U, "inModelView0", 1, instanceVBO.id()); // instance data layout