Custom type in VBO

I have a particle system with a Particle struct. My particle system moves the particles around every frame. In order to draw efficiently, I am using a VBO to draw the particles as points. Currently, in order to update the VBO with the new particle positions every frame, I have to extract the position from my vector of particles, build a new vector of ofVec3fs, and then copy that back into the VBO. However, this extra step is computationally inefficient.

If I was coding in raw OpenGL, I would copy the entire Particle struct to the VBO and setup the vertex attrib pointers with the correct offsets and strides to avoid the need for a second copy. How do achieve this with the ofVBO class?

You need to call ofVbo::setAttributeData, for the location parameter you need to call ofShader::getAttributeLocation, with the name of your attribute declared in GLSL code.

See how the other attributes are used in ofVbo (positionAttribute, colorAttribute, etc.), yours will go to ofVbo::customAttributes

My issue is with the param to actually pass the data into the set attribute data function. It accepts only float * types, whereas I would need to pass it a Particle *.

I don’t think you can, you shouldn’t be building new vector every time, you should just access the positions to be uploaded. You should probably keep your positions on a persistent vector and have your particles reference those via pointer.

Note
From of samples and particle addons, you can see that another good way of making this efficient is computing new particle positions via shaders, and encoding positions to colours. Check the gpuParticleSystemExample

you can upload any type, as long as it’s POD, meaning pure data only, no pointers… to a vbo putting it first in an ofBufferObject like:

class Particle{
    ofVec3f pos;
    ofVec3f vel;
    ofVec3f acc;
    ofFloatColor color;
}

std::vector<Particle> particles;
ofBufferObject buffer;

...
buffer.allocate(particles, GL_STATIC_DRAW);
vbo.setAttributeBuffer(shader.getLocation("position"), buffer, 3, sizeof(Particle), offsetof(Particle, pos));
vbo.setAttributeBuffer(shader.getLocation("velocity"), buffer, 3, sizeof(Particle), offsetof(Particle, vel));
vbo.setAttributeBuffer(shader.getLocation("acceleration"), buffer, 3, sizeof(Particle), offsetof(Particle, acc));
vbo.setAttributeBuffer(shader.getLocation("color"), buffer, 4, sizeof(Particle), offsetof(Particle, color));

then use buffer.updateData(particles) to update the particles in the gpu as long as the size of the vector hasn’t grown

you can omit any of the attributes if you don’t need them in your shader.

Thanks @arturo, this is exactly what I need.

@chuckleplant For now my computation is all done on CPU side, but the goal is to eventually port this to be a GPU driven system, hence my desire to copy the entire Particles struct into the VBO

1 Like