Deprecated VboMesh Functionality

I’m trying to wrap my head around the use of VboMeshes in Cinder, and finding the idea of Attributes and buffers confusing. Constructing a mesh purely in OpenGL isn’t a problem, but keeping track of the current method of building a VboMesh is Cinder is tough. I found a couple of functions that seem to have been removed in more recent releases, that would pretty much completely solve my problem.

What happened to the .bufferColorsRgb() and .bufferPositions() functions?

Those functions were from the pre “modern opengl” release of cinder (0.9+). Have a read of the guides to get up to speed with the current approach.

The guides were extremely helpful, but don’t cover any sort of custom mesh, it all relies on using the predefined geom:: sources. And all of the good (easily understood) sample code I can find is from those pre-modern days.

If you have an up-to-date resource that covers this, even something as simple as generating a single triangle from three vec3 positions, please let me know!

Sorry, i’m a bit rushed for time so I can’t answer properly, but a simple way is to go via a TriMesh.

TriMesh mesh { TriMesh::Format().positions() };
mesh.append /* blah */

auto vbo = gl::VboMesh::create ( triMesh );

Something like that.

also if you grep for bufferAttrib and mapAttrib in the samples/_opengl folder some more advanced stuff will pop up.

Oh, interesting.

I wonder if going this route would give me a performance boost…

Thank you for taking what little time you had to point me in the right direction!

Hi,

just to briefly summarize how to use the VboMesh class: it’s simply a set of arrays, describing the position of every vertex, as well as other vertex attributes like color, texture coordinate, normal, tangent, etc. The data is initialized and constructed on the CPU, then sent to GPU memory.

If the mesh does not change, you only have to send it once and then you can draw it an infinite amount of times. If the mesh does change, however, you can replace the data with a new copy, or iterate over the existing data to update it using the mapAttrib*() functions. The latter is more efficient, especially when using the orphanExisting = true flag. Because when this flag is set to true, the GPU allocates a second buffer for the new data, so that it can keep using the original buffer while the data is being updated. Updating the data usually takes a while and this way the GPU does not have to wait at all. For more in-depth info, see this presentation.

Cinder defines a bunch of default attributes: COLOR, TEX_COORD_0 / 1 / 2 / 3, NORMAL, TANGENT, BITANGENT, BONE_INDEX and BONE_WEIGHT. All of these are optional. Additionally, you can add up to 10 custom attributes using the CUSTOM_0 to CUSTOM_9 enums. Each attribute can store up to 4 floats (e.g. float, vec2, vec3, vec4).

You can then access those attributes in your vertex shader:

in vec4 ciPosition;
in vec4 ciColor;
in vec2 ciTexCoord0;
in vec3 ciNormal;
in vec3 ciTangent;
in vec3 ciBitangent;
in ivec4 ciBoneIndex;
in vec4 ciBoneWeight;

Edit: since the custom attributes can be used for anything at all, Cinder does not provide an automatic ciCustom0 mapping. Instead, specify the name either in gl::GlslProg::Format().attrib( geom::CUSTOM_0, "myAttributeName" ) or when creating the batch: auto batch = gl::Batch::create( mesh, glsl, { { geom::CUSTOM_0, "myAttributeName" } } );

To learn more about how to setup a mesh, have a look at this sample. The sample uses a vertex shader to update the mesh, which is slightly more advanced. But to learn how to update from the CPU, see this Cinder sample. Edit: to see a use case of custom attributes, check out this sample.

-Paul

4 Likes

Exactly what I needed! It’d be great to add that explanation to the new OpenGL guide.

1 Like