I want to draw lines by using my mouse. To do so, I am using a buffer object.
I am trying to store the location coordinates of the place where the mouse clicks, as the vertices of these lines. These vertices are being stored in the array variable that I have created but the lines are not being drawn.
The following is the important code:
typedef struct {
float x;
float y;
} vec2;
vec2 hotSpot[1000];
hotSpot is the variable where I store the vertex values. The buffer has been initialized as such:
glBufferData( GL_ARRAY_BUFFER, sizeof(hotSpot), NULL, GL_STATIC_DRAW);
In the mouse() function, I store the value of the coordinates in hotSpot, whenever I click. As I understand, the main() function is always in a loop. So this is what I have written in the main() function:
glBufferData(GL_ARRAY_BUFFER, 0, sizeof(hotSpot), &hotSpot);
Then in the display() function, this is what I do:
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_LINES, 0, 2);
glFlush();
Am I going wrong somewhere?
As I understand, the main() function is always in a loop.
No, the main function doesn't loop. Surely your program has a event loop, oftenly called the "main event loop", but this is not tied to the function "main".
A better method for you was not reuploading the whole buffer, but use glBufferSubData` to update just the one entry on the buffer that marks the next mouse position. This also allows you to do away with that large static buffer in your program. You just create a buffer object of the right size and do some bookkeeping (size of the buffer, current number of clicks stored).
Related
I am currently learning GFLW and OpenGL in C++, and I have come across a very weird error that I really can't figure out why it is occurring. I have two Vertex Buffers, one contains the data for a triangle, and the other contains data for a cube. When I create the Vertex Buffer for the Triangle and draw it without creating the Vertex Buffer for the Cube, it works perfectly and draws to the window the expected triangle. However, if I create the second Vertex Buffer and draw only the triangle again it becomes distorted.
Output when only the triangle Vertex Buffer is created:
Output when both the triangle Vertex Buffer and Cube Vertex Buffer are created (cube vertex buffer is never used)
Vertex Buffer's constructor
VertexBuffer(const GLvoid *data, GLsizeiptr size, GLenum mode, GLsizei count, GLsizei stride, ShaderInterface *shader, GLvoid *positionOffset, GLvoid *normalOffset);
Creating the two vertex buffers:
VertexBuffer *vertexBuffer=new VertexBuffer(vertices,sizeof(vertices),
GL_TRIANGLES,
3,
sizeof(GL_FLOAT)*3,
shaderArray->at(0),
NULL,
NULL);
vertexBufferArray->push_back(vertexBuffer);
VertexBuffer *cubeVertexBuffer=new VertexBuffer(cubeVertices,
sizeof(cubeVertices),
GL_TRIANGLES,
36,sizeof(VertexDataPN),
shaderArray->at(1),
(GLvoid*)(offsetof(VertexDataPN,positionCoordinates)),
(GLvoid*)(offsetof(VertexDataPN,normalCoordinates)));
//vertexBufferArray->push_back(cubeVertexBuffer);
And the contents of the constructor for my Vertex Buffer class:
glGenBuffers(1,&vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER,vertexBufferID);
glBufferData(GL_ARRAY_BUFFER,size,data,GL_STATIC_DRAW);
Also, I have already checked that the vertexBufferID's are different for both of them. The Cube Vertex Buffer is never used or referenced to after it gets created. If anyone knows why this is occurring please let me know.
OpenGL is state-based, which means that objects that change OpenGL's internal state during their initialization can affect its behaviour even if they aren't subsequently used.
You are calling glBindBuffer in your vertex buffer constructor, which means that unless you call glBindBuffer later, the most recently bound buffer (the cube) will remain bound to GL_ARRAY_BUFFER and will be used during rendering.
You need to change your drawing code to call glBindBuffer with the buffer that you intend to use (e.g. the triangle one), before any calls to glVertexAttribPointer.
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 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_
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.