0
\$\begingroup\$

I'm making some tests with rendering stuff and I'm wondering how to design my Geometry class. For the moment, here is how I do:

  • Init: Stock array with positions, array with colors, array with normals, … has attributes.
  • Just before rendering, if my geometry have changed, I update his vertex buffer and index buffer. To do that, I compute interleaved array here and send it to my vertex buffer.

I've made some tests with particles (10000 on iPad), the heaviest function is "Geometry::computeInterleavedArray.

How can I avoid this part? Is it better to stock geometry's data inside a single array with all data already interleaved?

\$\endgroup\$
2
\$\begingroup\$

The most efficient method of updating vertex data would be to do it on the GPU. To do this you can use transform feedback. Transform feedback works by letting you write out changes to your vertices in the vertex shader back to your vertex buffer.

Or if you need to calculate the positions cpu side for some reason, glMapBufferRange may be the next best thing. I'm assuming at the moment you are doing something along the lines of:

GLuint myVBO;
glm::vec3 positions[10000];
glm::vec3 colours[10000];
glGenBuffers(1, &myVBO);
//Update
for(...)
    position[i]+=velocity[i];
// Upload
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*10000, &positions[0], GL_DYNAMIC_DRAW);
// Render

Instead you can do:

// (Not complete code)
GLuint myVBO;
glGenBuffers(1, &myVBO);
glm::vec3 positions[10000];
glm::vec3 colours[10000];
// Set initial positions
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*10000, &positions[0], GL_DYNAMIC_DRAW);
//Update
glm::vec3 * gpuPositions = glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3)*10000, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
for(...)
    gpuPositions[i]+=velocity[i];
glUnmapBuffer(GL_ARRAY_BUFFER);
// Render

These are OpenGL es 3.0 features. So may not be available on your device. If you need es 2.0, you are not going to get much more speed than uploading with glBufferData() each frame. If you are doing something along the lines of:

for(...)
    interleavedArray[i] = positions[i];
    interleavedArray[i+3] = colours[i];

Then yes it would be more efficient to store the data already interleaved like:

for(...)
    interleavedArray[i+positionOffset] += velocity[i];
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.