I am generating the vertex arrays on the fly on each render and I want to delete the arrays afterwards. Does glDrawArrays immediately copy the vertex arrays to the server? Hence is it safe to delete the vertex arrays after calling glDrawArrays?
float * vp = GetVertices(); // Regenerated on each render
glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), vp);
glDrawArrays(GL_TRIANGLES, 0, nVertices);
delete[] vp; // Can I do this?
Otherwise, how can I determine when it is safe to delete the vertex arrays?
Yes, it is copied immediately, so once you've done the call you can do whatever you like with the array.
Also, as dirkgently pointed out, you need to use delete[] vp to delete an array.
Yes, you can delete the vertex array after calling glDrawArrays. But opengl won't store vertex data in it's memory. It will just use the vertex array and draws on the frame buffer. So next time if you want draw the same vertex, then you have to provide the vertex array again to glDrawArrays.
Related
I've got a problem with drawing an buffer object with no index. My other indexed vbos draw fine...
void drawArray(VertexArrayObject VAO)
{
GL11.glColor3d(1.0f, 0.2f, 0.2f);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VAO.southSkirtBufferID);
GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, VAO.southSkirtLength);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
}
You are not using your "skirt buffer" for drawing. In drawArray you actually set the vertex pointer to point to the offset 0 in VAO.vertexBufferID (whatever that is, at that time. And you never set it to anything else.
The buffer reference is a part of the vertex attribute pointer, the currently bound GL_ARRAY_BUFFER at the time of the gl*Pointer() call will be used for that pointer. The GL_ARRAY_BUFFER binding at the time of the draw call is totally irrelevant, and just changing that binding does not affect the attribute pointers.
If you only render the skirts, it crashes because your attribute pointers aren't set up to anything useful at all.
I have a subfunction that reads a data stream and creates an array of vertex data based on that. The main function calls this subfunction repeatedly and updates the vertex data array, which is then bound to a buffer and drawn. So far, so good. However, I cannot figure out how to add vertices. C++ does not let you reassign or resize entire arrays. I can't use vectors because the OpenGL functions take in arrays, not vectors.
You can use vectors to populate an OpenGL vertex buffer. The values in a vector are guaranteed to be contiguous. See for example these discussions for details on the related language standards:
Are std::vector elements guaranteed to be contiguous?
Is it safe to assume that STL vector storage is always contiguous?
This means that code like the following is safe:
std::vector<GLfloat> vertexPositions;
// Populate vector with vertex positions.
GLuint bufId = 0;
glGenBuffers(1, &bufId);
glBindBuffer(GL_ARRAY_BUFFER, bufId);
glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(GLfloat),
&vertexPositions[0], GL_STATIC_DRAW);
The subtle but critical part is that you pass in the address of the first element of the vector, not the address of the vector object.
I would make a slight edit. While you can use &vertexPositions[0] as the address of the beginning of an STL vector, I prefer to use the function designed to return the address of the beginning of the vector memory, vertexPositions.data().
std::vector<GLfloat> vertexPositions;
// Populate vector with vertex positions.
GLuint bufId = 0;
glGenBuffers(1, &bufId);
glBindBuffer(GL_ARRAY_BUFFER, bufId);
glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(GLfloat), vertexPositions.data(), GL_STATIC_DRAW);
I use STL vectors for OGL data for a number of reasons. It's easy to preallocate if you know the size, and they will grow (and stay contiguous) when you add items. They are easy to iterate through. You can easily create vectors of structures if you want to pass in interleaved data. It all works the same.
I have particle and particle system class. In my main program, I created an instance of particle system and initialized the particles in it. In the display function, I would like to pass the position of all particles to the Vertex buffer in one shot. But I'm not sure of the notation used to access all position vertices from the.
class particle{
glm::vec3 pos;
glm::vec3 vel;
}
class particleSystem{
std::vector<particle> m_particles;
}
I tried something like this:
//Displaying particles starts here
glGenBuffers(1, &particleBuffers);
glBindBuffer(GL_ARRAY_BUFFER, particleBuffers);
glBufferData(GL_ARRAY_BUFFER, sizeof(ps.m_particles[].pos), ps.m_particles[].pos, GL_STATIC_DRAW);
glVertexAttribPointer(position_loc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_POINTS, 0, (GLsizei)ps.m_particles.size()); //Draw them to screen
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Displaying particles ends here
where ps is an instance of the particlesystem class. The notation I used to access all positions of the particles in the glBufferData function does not work. Any suggestions?
I would consider uploading the entire particle vector to the GPU like this:
struct particle {
glm::vec3 pos;
glm::vec3 vel;
};
[...]
glBufferData (GL_ARRAY_BUFFER, sizeof (particle) * ps.m_particles.size (),
&ps.m_particles [0], GL_STATIC_DRAW);
glVertexAttribPointer (position_loc, 3, GL_FLOAT, GL_FALSE, sizeof (particle), 0);
I am not sure how your original code actually worked, these fields have private access by default if you declare particle as a class.
There are two points to mention here:
&ps.m_particles [0] is the standard method to acquire a pointer to a contiguous block of memory representing your vector's data store.
Since your particle data structure contains two fields, your stride is non-zero.
This is the second-to-last parameter in the call to glVertexAttribPointer (...).
Alternatively, you might consider a separate data structure to store the data you actually need for rendering from the data you need for CPU-side simulation:
struct particle_vtx {
glm::vec3 pos;
//glm::vec3 color;
};
struct particle_state {
glm::vec3 vel;
//GLuint texture;
};
[...]
class particleSystem {
std::vector<particle_vtx> m_particle_verts;
std::vector<particle_state> m_particle_states;
};
This is probably the more versatile solution in the end, because you will have two pools of contiguous memory that separate what the GPU needs from what the CPU needs. You will be much more memory efficient (on the GPU side) and will not require any special processing when it comes time to send the vertex data to the GPU. Granted stateful particle systems can be implemented completely on the GPU these days, start small.
You have to pass an integer value into the vector array operator. If you are trying to create an array of glm::vec3 to pass into glBufferData, you'll have to do so manually - probably through use of a for loop and dynamic allocation.
I have a struct to store vertex data for 2 distinct models one is a cube the other a pyramid.
struct Model{
GLuint vboID;
GLfloat* vbo;
GLuint vaoID;
GLfloat* vao;
GLuint vertexStart;
GLuint vertexCount;
};
I create the vbos and generate their buffers like this:
Model cubeModel;
Model pyramidModel;
cubeModel.vbo = cubeVerts; //A GLfloat array I created earlier in code earlier.
cubeModel.vertexCount= sizeof(cubeVerts);//size of the GLfloat array in bytes
pyramidModel.vbo = pyVerts;
pyramidModel.vertexCount= sizeof(pyVerts);
glGenBuffers(1, &cubeModel.vboID); //Generate a buffer for the vertices
glBindBuffer(GL_ARRAY_BUFFER, cubeModel.vboID); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, cubeModel.vertexCount, cubeModel.vbo, GL_STATIC_DRAW);
And then to draw I use:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, cubeModel.vertexCount);
glDisableClientState(GL_VERTEX_ARRAY);
Which works, and I successfully draw the cube, But i've been trying multiple ways to draw the pyramid as well.
What do I need to do to render both on screen at the same time?
EDIT: Here's what i've tried specifically, duplicating the glBufferData() call and passing in the pyramid data then making glDrawArays(GL_TRIANGLES,0,cubeModel.drawcount+pyramidModel.drawCount) figuring the vertex data would stack and glDrawArrays would go through all the geometry passed in one go.
I've also tried making 2 sets of instructions from glGenBuffers() to glDisableClientState() but instead using all of pyramid model's data. This was interesting because my glDrawArrays was:
glDrawArrays(GL_TRIANGLES, 0, cubeModel.drawCount);
glTranslatef(4.0f,0.0f,0.0f);
glDrawArrays(GL_TRIANGLES, 0, pyramidModel.drawCount);
and it ended up drawing a really messed up pyramid 2 times, leading me to believe that when I cal glBufferData() twice the second time Overwrites the data previously passed.
EDIT 2:After Reading Andon's comment I edited some of my code to clarify things, drawCount is now vertexCount, and m_vertexBuffer is now correctly referencing the handle I stored in cubeModel, cubeModel.vboID, instead of using an old class variable I was using to store the handle.
I do not want to muddy up the comments section, because there are a lot of things wrong with your code. But I also do not have time to go through all of them right now, so this is a sort of temporary answer.
glBufferData (...) does not technically overwrite previously passed data, it does something far worse. Every time you call glBufferData (...) it creates a new data store of the size you pass and (optionally) fills it with the data you supply (if you pass something non-NULL). Think of it more like calling free (...) and then malloc (...) or delete [] ... and new Type [...].
glBufferSubData (...) is the preferred technique for appending vertices to a vertex buffer. Unfortunately it does not resize the data store. Sometimes it is handy to over-allocate your VBO and defer supplying it data until later on (using glBufferSubData).
If you use one VBO to store both of your models, you need to know the starting vertex and the vertex count for each model as it relates to your VBO's data. Right now all you know is the number of vertices (and you have it named strangely drawCount instead of vertexCount). To most people, drawCount indicates the number of times you want to draw something, rather than the number of vertices or elements it contains.
The size field of a call to glBufferData (...) is supposed to be the size in bytes of your vertex data. Right now you're passing the number of vertices. More than likely you meant to use sizeof (YourVertexDataStructure) for the size of an individual vertex (sizeof (float [3]) in this case), and something like sizeof (cubeVerts) / sizeof (YourVertexDataStructure) to calculate the number of vertices actually stored in this array. Then the size you pass to glBufferData (...) would be: _size * count_
What is the best way to store dynamic data for use in VBO (or vertex arrays). Only examples I saw were 2D static arrays and the pointer to that array was used with next parameters as stride, bytes used for one element etc. I can use "dynamic" arrays so I can specify it's size on-air, but just once. My point is that if you, for example, already drawing 1000 points (talking about 2D so I think point is better then vertex) as line strip and you add new point, this way you have to make new array with size of 1001, copy everything from old to new field, add new point and send it down to graphic's memory. Best way is to use vectors or deques as temporary storage, but then I have to convert to array and again send it down.
So is there better way to do this? Can I only add new part to VBO without sending down the old data? Or better way to store data/using vector as data source without conversion?
I usually just use the 'ole vector trick:
struct GL_Vertex
{
Eigen::Vector2f tex;
Eigen::Vector3f color;
Eigen::Vector3f pos;
};
...
vector<GL_Vertex> buf(1000);
...
glTexCoordPointer( 2, GL_FLOAT, sizeof(GL_Vertex), &buf[0].tex );
glColorPointer( 3, GL_FLOAT, sizeof(GL_Vertex), &buf[0].color );
glVertexPointer( 3, GL_FLOAT, sizeof(GL_Vertex), &buf[0].pos );