4

Currently I'm writing a program that simulates water. Here are the steps that I do:

  1. Create water surface - plane.
  2. Create VAO
  3. Create vertex buffer object in which I store normals and vertices.
  4. Bind pointers to this VBO.
  5. Create index buffer object.

Then I render this plane using glDrawElements and then I invoke an update() function which changes positions of vertices of water surface. After that I invoke glBufferSubData function to update vertices positions.

When I do that - nothing happens as if the buffer isn't changed.

Here's the code snippet:

glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Oscillator) * nOscillators, oscillators, GL_DYNAMIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Oscillator), 0);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Oscillator), (const GLvoid*)12);
glEnableVertexAttribArray(0);  // Vertex position
glEnableVertexAttribArray(2);  // normals position

glGenBuffers(1, &indicesBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * nIndices, indices, GL_DYNAMIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer);
glBindVertexArray(0);

Then render:

glBindVertexArray(vaoHandle);
glDrawElements(GL_TRIANGLES, nIndices, GL_UNSIGNED_INT, 0); 
update(time);

And update function:

//some calculations
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Oscillator) * nOscillators, oscillators);

Oscillator - it's a structure that has: 8 floats respectively - x, y, z (vertex position), nx, ny, nz (normals), upSpeed, newY

oscillators - this is an array of Oscillator structures.

What I do wrong?

Shot
  • 345
  • 5
  • 19
  • Does the water render correctly before you call update? – Andreas Brinck Dec 17 '12 at 12:10
  • Do you clear the color buffer/depth buffer/... before you call draw again? – Mircea Ispas Dec 17 '12 at 12:17
  • Yes, water renders correctly and I clear color and depth buffers. – Shot Dec 17 '12 at 12:34
  • 2
    Have you bound the correct buffer before the call to `glBufferSubData`? – Andreas Brinck Dec 17 '12 at 13:18
  • Thanks - it works now :) :D Can I update severals buffers simultaneously? I mean - first I update water surface vertex position buffer and then I update particles positions buffer. – Shot Dec 17 '12 at 13:46
  • 1
    Yes, you can. Bind first buffer and update it, next bind second buffer and update it. Binding the GL_ARRAY_BUFFER does not affect attribute pointers set in the VAO. But note that updates are not simultaneous since `glBufferSubData()` call are synchronous. – Oleg Titov Dec 17 '12 at 14:37

1 Answers1

1

Before updating the data you have to bind the correct buffer. E.g:

glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

Since you are updating the full buffer at once I would suggest to use glMapBuffer to update it

void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
//[...] update the buffer with new values
bool done = glUnmapBuffer(GL_ARRAY_BUFFER);

And remember to wait (or force) a glFlush() before modifying the data you are goin to copy to the gl buffer.

Pierluigi
  • 2,212
  • 1
  • 25
  • 39