Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ACG::SceneGraph::ACG::VertexDeclaration Class Reference

Class to define the vertex input layout. More...

Public Member Functions

void addElement (const VertexElement *_pElement)
 
void addElement (unsigned int _type, unsigned int _numElements, VERTEX_USAGE _usage, const void *_pointer, const char *_shaderInputName=0, unsigned int _divisor=0, unsigned int _vbo=0)
 
void addElement (unsigned int _type, unsigned int _numElements, VERTEX_USAGE _usage, size_t _byteOffset=0, const char *_shaderInputName=0, unsigned int _divisor=0, unsigned int _vbo=0)
 
void addElements (unsigned int _numElements, const VertexElement *_pElements)
 
void clear ()
 
void activateFixedFunction () const
 
void deactivateFixedFunction () const
 
void activateShaderPipeline (GLSL::Program *_prog) const
 
void deactivateShaderPipeline (GLSL::Program *_prog) const
 
void setVertexStride (unsigned int _stride)
 
unsigned int getVertexStride (unsigned int i=0) const
 
unsigned int getNumElements () const
 
const VertexElementgetElement (unsigned int i) const
 
int findElementIdByUsage (VERTEX_USAGE _usage) const
 
const VertexElementfindElementByUsage (VERTEX_USAGE _usage) const
 
QString toString () const
 

Static Public Member Functions

static unsigned int getGLTypeSize (unsigned int _type)
 
static unsigned int getElementSize (const VertexElement *_pElement)
 
static bool supportsInstancedArrays ()
 

Private Member Functions

void updateOffsets ()
 
void updateShaderInputName (VertexElement *_pElem)
 

Private Attributes

std::vector< VertexElementelements_
 
unsigned int vertexStride_
 Offset in bytes between each vertex.
 
std::map< unsigned int,
unsigned int > 
vertexStridesVBO_
 Map vbo to offset in bytes between each vertex in that vbo.
 
int strideUserDefined_
 Flag that indicates, whether the stride was set by user or derived automatically.
 

Detailed Description

Class to define the vertex input layout.

This class is used to specify vertex data layout (normals,positions,...).

The layout of a vertex buffer typically includes:

  • number of vertex elements
  • element usage (position, normal, ... )
  • element types (float, int, ...)
  • memory alignment
  • 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

Create a vertex declaration given the following vertex data:

Vertex
{
float4 pos
float3 normal
float2 texcoord
ubyte4 color
float4 tangent
float2 texcoord2
}

The accompanying vertex declaration is created as follows:

VertexDeclaration decl;
decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_POSITION);
decl.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL);
decl.addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD);
decl.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR);
decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, 0U, "inTangent");
decl.addElement(GL_FLOAT, 2, VERTEX_USAGE_SHADER_INPUT, 0U, "inTexcoord2");

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:

in vec4 inPosition;
...
in vec4 inTangent;
in vec2 inTexcoord2;

VERTEX_USAGE_SHADER_INPUT is ignored in fixed function pipeline


Example usage: Multiple source buffers in system memory

Given are system memory buffers as vertex data source for drawing:

float4* pVertexPositions;
ubyte4* pVertexColors;
float3* pVertexNormals;

It is important that the vertex stride is manually set to 0!! and that the element data pointers are set accordingly:

VertexDeclaration decl;
decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_POSITION, pVertexPositions);
decl.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL, pVertexNormals);
decl.addElement(GL_UNSIGNED_BYTE, 4, VERTEX_USAGE_COLOR, pVertexColors);
decl.setVertexStride(0);

Note:

  • vertex stride = 0
  • assign data address in vertex elements and don't change the data location later
  • 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:

Vertex
{
float4 pos
float3 normal
float2 texcoord
}

Each instance of this mesh should have a different world transform and a different color. So the per instance data is:

InstanceData
{
mat4 modelview
uint color
}

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:

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
decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, 0U, "inModelView1", 1, instanceVBO.id());
decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, 0U, "inModelView2", 1, instanceVBO.id());
decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, 0U, "inModelView3", 1, instanceVBO.id());
decl.addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR, 0U, 0, 1, instanceVBO.id());

The 4x4 modelview matrix has to be split up into float4 elements.

Using this setup, a call to decl.activateShaderPipeline() is enough to prepare an instanced draw call.

Finally, instancing requires a customized vertex shader that makes use of the per instance data:

..
in vec4 inModelView0;
in vec4 inModelView1;
in vec4 inModelView2;
in vec4 inModelView3;
..
void main()
{
..
vec4 posVS;
posVS.x = dot(inModelView0, inPosition);
posVS.y = dot(inModelView1, inPosition);
..
gl_Position = projection * posVS;
}

Definition at line 266 of file MeshNode2T.cc.

Member Function Documentation

void ACG::SceneGraph::ACG::VertexDeclaration::activateFixedFunction ( ) const

prepare OpenGL to use a vertex buffer with this declaration -> uses the fixed function pointers (glVertexPointer, glColorPointer...)

void ACG::SceneGraph::ACG::VertexDeclaration::activateShaderPipeline ( GLSL::Program _prog) const

prepare OpenGL to use a vertex buffer with this declaration -> uses shader attribute pointers ( glVertexAttribPointer )

void ACG::SceneGraph::ACG::VertexDeclaration::addElement ( const VertexElement _pElement)

append one element to declaration

void ACG::SceneGraph::ACG::VertexDeclaration::addElement ( unsigned int  _type,
unsigned int  _numElements,
VERTEX_USAGE  _usage,
const void *  _pointer,
const char *  _shaderInputName = 0,
unsigned int  _divisor = 0,
unsigned int  _vbo = 0 
)

append one element to declarations, direct method

void ACG::SceneGraph::ACG::VertexDeclaration::addElement ( unsigned int  _type,
unsigned int  _numElements,
VERTEX_USAGE  _usage,
size_t  _byteOffset = 0,
const char *  _shaderInputName = 0,
unsigned int  _divisor = 0,
unsigned int  _vbo = 0 
)

append one element to declarations, direct method

void ACG::SceneGraph::ACG::VertexDeclaration::addElements ( unsigned int  _numElements,
const VertexElement _pElements 
)

append multiple element declarations

void ACG::SceneGraph::ACG::VertexDeclaration::clear ( )

remove all vertex elements, also clears the user defined stride flag

void ACG::SceneGraph::ACG::VertexDeclaration::deactivateFixedFunction ( ) const

disables vertex attributes to prevent any draw related crashes

void ACG::SceneGraph::ACG::VertexDeclaration::deactivateShaderPipeline ( GLSL::Program _prog) const

disables this vertex declaration to prevent any draw related crashes -> calls glDisableVertexAttribArray

const VertexElement* ACG::SceneGraph::ACG::VertexDeclaration::findElementByUsage ( VERTEX_USAGE  _usage) const

find element ptr by usage, return 0 if not found

int ACG::SceneGraph::ACG::VertexDeclaration::findElementIdByUsage ( VERTEX_USAGE  _usage) const

find element id by usage, return -1 if not found

const VertexElement* ACG::SceneGraph::ACG::VertexDeclaration::getElement ( unsigned int  i) const

get the i'th vertex element desc

static unsigned int ACG::SceneGraph::ACG::VertexDeclaration::getElementSize ( const VertexElement _pElement)
static

get size of one vertex element

static unsigned int ACG::SceneGraph::ACG::VertexDeclaration::getGLTypeSize ( unsigned int  _type)
static

get size of GL_FLOAT, GL_INT ...

unsigned int ACG::SceneGraph::ACG::VertexDeclaration::getNumElements ( ) const

get num of vertex elements

unsigned int ACG::SceneGraph::ACG::VertexDeclaration::getVertexStride ( unsigned int  i = 0) const

get vertex size (for element i, for multi vbo support)

void ACG::SceneGraph::ACG::VertexDeclaration::setVertexStride ( unsigned int  _stride)

set vertex stride manually, otherwise it is computed from the vertex elements

static bool ACG::SceneGraph::ACG::VertexDeclaration::supportsInstancedArrays ( )
static

Check hw support for streaming instance data from vbo

QString ACG::SceneGraph::ACG::VertexDeclaration::toString ( ) const

Returns a string describing the vertex format for debugging purpose.

void ACG::SceneGraph::ACG::VertexDeclaration::updateOffsets ( )
private

automatically computes byte offset for interleaved vertex elements and computes vertex stride

void ACG::SceneGraph::ACG::VertexDeclaration::updateShaderInputName ( VertexElement _pElem)
private

automatically sets shader input name on passed element, if not provided


The documentation for this class was generated from the following file: