2

Problem I have a vector of pointers to particles:

struct Particle {
    vec3 pos; // just 3 floats, GLM vec3 struct
    // ...
}
std::vector<Particle *> particles;

I want to use this vector as the source of data for an array buffer in OpenGL Like this:

glGenBuffers(1, &particleBuffer);
glBindBuffer(GL_ARRAY_BUFFER, particleBuffer);
int bufferSize = sizeof(Particle) * particles->size();
glBufferData(GL_ARRAY_BUFFER, bufferSize, /* What goes here? */, GL_STATIC_DRAW);

glEnableVertexAttribArray(positionAttribLocation);
glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (void *)0);

Where the interesting line is glBufferData( ... )

How do I get OpenGL to get that the data is pointers?

2
  • 2
    "Problem: I have a vector of pointers to particles:": Solution: Stop using a vector of pointers to particles ;) But seriously, don't do that. And not just because OpenGL doesn't work with indirect data structures like that. Commented Mar 2, 2017 at 21:51
  • I guess this might be useful? stackoverflow.com/questions/2923272/… Commented Mar 2, 2017 at 21:51

2 Answers 2

5

How do I get OpenGL to get that the data is pointers?

You don't.

The whole point of buffer objects is that the data lives in GPU-accessible memory. An pointer is an address, and a pointer to a CPU-accessible object is a pointer to a CPU address. And therefore is not a pointer to GPU-accessible memory.

Furthermore, accessing indirect data structures like that is incredibly inefficient. Having to do two pointer indirection just to access a single value basically destroys all chance of cache coherency on memory accesses. And without that, every independent particle is a cache miss.

That's bad. Which is why OpenGL doesn't let you do that. Or at least, it doesn't let you do it directly.

The correct way to do this is to work with a flat vector<Particle>, and move them around as needed.

Sign up to request clarification or add additional context in comments.

Comments

0

glBufferData requires a pointer to an array of the data you wish to use. In your case, a GLfloat[] would be used for the vertices. You could write a function which creates a GLfloat[] from the vector of particles. The code I use creates a GLfloat[] and then passes it as a pointer to a constructor which then sets the buffer data. Here is my code;

Creating the Vertex Array - GlFloat[]

GLfloat vertices[] = {  0, 0, 0, 
                        0, 3, 0,
                        8, 3, 0,
                        8, 0, 0  };

After I have created the vertices I then create a buffer object (Which just creates a new buffer and sets it's data);
Buffer* vbo = new Buffer(vertices, 4 * 3, 3);

The constructor for my buffer object is;

Buffer::Buffer(GLfloat* data, GLsizei count, GLuint componentCount) {
    m_componentCount = componentCount;

    glGenBuffers(1, &m_bufferID);
    glBindBuffer(GL_ARRAY_BUFFER, m_bufferID);
    glBufferData(GL_ARRAY_BUFFER, count * sizeof(GLfloat), data, GL_STATIC_DRAW); //Set the buffer data to the GLFloat pointer which points to the array of vertices created earlier.
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

After this array has been passed to the buffer, you can delete the object to save memory however it is recommended to hold onto it in case it is reused later.

For more information and better OpenGL practices I recommend you check out the following youtube playlist by TheChernoProject.
https://www.youtube.com/watch?v=qTGMXcFLk2E&list=PLlrATfBNZ98fqE45g3jZA_hLGUrD4bo6_&index=12

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.