Okay, I’ll detail the instance VBO update now:
What I have :
- A list of instanced drawing algorithm (meshes)
- A list of pairs offset/count
- A list of matrices
- Instanced VBO sized say 2MBytes
Now I want to render a mesh with instancing, I get its offset/matrix_count (also the number of instances to render) pair, bind the VBO to the range associated with the instance, and set the matrices. Then I perform the draw call. On to the next mesh, map the new range, set matrices of the instances, and so on. But these ranges are computed every cycle (using the result of visibility culling algorithms, user parameters, etc… )
Here’s some pseudo code for drawing
for each mesh
// map the buffer.
glBindBuffer(GL_ARRAY_OBJECT, instanceBufferID);
// if offset+numInstances is bigger than VBO size, orphan.
float* data = (float*)glMapBufferRange(GL_ARRAY_OBJECT, currentMesh.offset, currentMesh.numInstancesToRender*sizeof(mat4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_FLUSH_EXPLICIT_BIT);
data = ¤tMesh.matrixArray[0];
glFlushMappedBufferRange();
// bind VAO, material, and draw
currentMesh.drawCall(currentMesh.numInstancesToRender);
Now here’s what the VAO construction would look like for my drawable objects:
// Enable Vertex Attrib Arrays
glEnableVertexAttribArray(semantic::vertex_pos);
glEnableVertexAttribArray(semantic::instance_mat_column0);
glEnableVertexAttribArray(semantic::instance_mat_column1);
glEnableVertexAttribArray(semantic::instance_mat_column2);
glEnableVertexAttribArray(semantic::instance_mat_column2);
// Bind vertex data
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glVertexAttribPointer(semantic::vertex_pos, 4, GL_FLOAT, GL_FALSE, 0, NULL);
// Bind instanced attributes
// I need some_const_val to be dynamic ...
glBindBuffer(GL_ARRAY_BUFFER, instanceBufferID);
glVertexAttribPointer(semantic::instance_mat_column0, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), some_const_val);
glVertexAttribPointer(semantic::instance_mat_column1, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), some_const_val+sizeof(GLfloat)*1);
glVertexAttribPointer(semantic::instance_mat_column2, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), some_const_val+sizeof(GLfloat)*2);
glVertexAttribPointer(semantic::instance_mat_column3, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), some_const_val+sizeof(GLfloat)*3);
// instanciate the perInstance_matrix attributes
glVertexAttribDivisor(semantic::instance_mat_column0,1);
glVertexAttribDivisor(semantic::instance_mat_column1,1);
glVertexAttribDivisor(semantic::instance_mat_column2,1);
glVertexAttribDivisor(semantic::instance_mat_column3,1);
My problem isn’t about updating the buffer but using it for the final draw calls : the pointer to the instanced attributes in my array buffer is changed (almost) every new rendering cycle.
Are you rendering a scene where “heavy use of instancing” would be useful?
Using one draw call instead of N>1 is better whenever possible, isn’t it ?