I've created a simple opengl program on Windows 7 using WIN api.
I've setup the window by following the tutorial on MSDN win api website.
The window works perfectly, even with input logging it does not leak any memory and works alright stays at 1.7 MB of ram.
With opengl context it takes 11MB.
If i want to draw something like Rectangle it begins to leak by 200 kb.
(The rectangle draws perfectly fine....)
It starts at 14.5 MB and grows up to 50MB and continues.
There are no 'new' keywords in the whole program, it is very simple program. Only create window. Than while loop in which the rendering is done...
Here is the main.
int main()
{
Window wind(800,600);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
while(!wind.isCloseRequested())
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
Vector3f Vertices[3];
Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f);
Vertices[1] = Vector3f(1.0f, -1.0f, 0.0f);
Vertices[2] = Vector3f(0.0f, 1.0f, 0.0f);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
wind.update();
Sleep(16);
}
wind.Destroy();
return 0;
}
glGenBuffers(1, &VBO);
make memory leak. You need create buffer one time and using it or destroy buffer every time with glDeleteBuffers
By the way, before using any OpenGL function I recommended read docs. Many OpenGL function allocate some internal buffers in memory or resources in GPU and need call delete/destroy.
Related
I searched for this and only found a post from 2014 asking about a somewhat similar situation. However, as I couldn't understand what was done there, I'm asking again, specifically for my implementation, hoping this sheds some light on the topic in general as well. I am fairly new to c++ and openGL, so please be so kkind as to excuse stupid mistakes.
I'm trying to implement a simple 2D HUD for my 3D game. Now, my game is fully rendered, due to having a bloom effect in my game, I even rendered my game on a screen quad.
What I now want to do ist placing a HUD over this rendered scene, I, however, can't seem to do that.
My screen quad for the game is drawn like so:
unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{
if (quadVAO == 0)
{
float quadVertices[] = {
// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// texCoords
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
// setup plane VAO
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
}
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
What I tried to do, ist change my renderQuad method to a renderHUDquad one by basically just changing the dimensions of the quad to make it appear in the bottom left corner of the screen.
The code looks as follows:
unsigned int HUDquadVAO = 0;
unsigned int HUDquadVBO;
void renderHUDQuad()
{
if (HUDquadVAO == 0)
{
float HUDquadVertices[] = {
// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// texCoords
0.0f, 0.02f,
0.0f, 0.0f,
0.2f, 0.0f,
0.0f, 0.02f,
0.2f, 0.0f,
0.2f, 0.02f
};
// setup plane VAO
glGenVertexArrays(1, &HUDquadVAO);
glGenBuffers(1, &HUDquadVBO);
glBindVertexArray(HUDquadVAO);
glBindBuffer(GL_ARRAY_BUFFER, HUDquadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(HUDquadVertices), &HUDquadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
}
glBindVertexArray(HUDquadVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
As this only needs to be a small green quad, i.e. a health bar for the player, I was thinking about just assigning it a green texture or sth..
However, when drawing my two quads like this:
// Third pass = Combined bloom pictures
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
bloomShader->use();
// Set uniform for multiple layout uniforms
bloomShader->setUniform("scene", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colorAndLightBuffers[0]);
// Set uniform for multiple layout uniforms
bloomShader->setUniform("bloomBlur", 1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pingpongBuffer[horizontal == 0 ? 1 : 0]);
bloomShader->setUniform("bloom", bloom);
bloomShader->setUniform("exposure", exposure);
renderQuad();
renderHUDQuad();
// Swap buffers
glfwSwapBuffers(window);
I only get the HUD element without any of the stuff I drew before as if the rest of the screen was rendered black. I thought I could just add this to the old buffer, as there a way to do this?
You did screw up your GL state very badly:
void renderHUDQuad() {
if (HUDquadVAO == 0)
{
[...]
glGenVertexArrays(1, &quadVAO);
You actually use quadVAO in the rest of this function, so you overwrite your fullscreen quad by the smaller one, which means the rest of your scene will be scaled down to this quad from the next frame on...
Hi so i have been basically pulling my hair out trying to understand this OpenGL confusion
i have tried to find answers in books, in tutorials , and even experimenting around with it
SO basically i have a opengl program that draws the first time my two triangles, however when i try to redraw the first triangle again it doesnt seem to be working
i dont know what information i am missing , but its no t making any sense
as far as i understand once the VAO and VBO have been created and bounded and buffered to memory, and vertex attrib pointers set and enabled that once i bind the vao object that i want to draw as many times as i like, i just have to do that
after initialization which works for me, the problem is that once i rebind another vao object it doesnt seem to draw it
my code is quiet long , i can paste it here if you like, but i think that the drawing part of the code would be sufficient
here it is
GLfloat vec[] = {0.0f, 0.0f,
1.0f, -1.0f,
-1.0f, -1.0f};
GLfloat vec2[] = {0.0f, 1.0f,
1.0f, 0.0f,
-1.0f, 0.0f};
//next step is to upload data to graphics memory
//generating a buffer from openGL
GLuint vbo;
GLuint vbo2 ;
GLuint vao;
GLuint vao2;
glGenBuffers(1, &vbo);
glGenBuffers(1, &vbo2);
glGenVertexArrays(1, &vao);
glGenVertexArrays(1, &vao2);
//to upload the actual data must make the object active by binding it to a target
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//upload the data of active object to memory
glBufferData(GL_ARRAY_BUFFER, sizeof(vec), vec, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vec2), vec2, GL_STATIC_DRAW);
//bind and draw
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays (GL_TRIANGLES, 0, 3);
glXSwapBuffers ( dpy, glxWin );
sleep(3);
glClear(GL_COLOR_BUFFER_BIT);
//rendering second triangle
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBindVertexArray(vao2);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays (GL_TRIANGLES, 0, 3);
glXSwapBuffers ( dpy, glxWin );
sleep(3);
//rendering the first triangle again------where the problem lies!!!
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays (GL_TRIANGLES, 0, 3);
glXSwapBuffers ( dpy, glxWin );
sleep(3);
You'll also need to clear the depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
If you follow a tutorial then you will probably have enabled depth testing in the openGL setup boilerplate it provided. This is because more people will want to use the depth buffer than not.
you can also not call glEnable(GL_DEPTH_TEST); during setup.
I recently created an OBJ loader, it works perfectly fine at the moment, which is without any VBO buffer objects. I am currently in the process of changing over to using VBO with my program and it crashes( doesn't respond) every time I try to run it.
My obj loader consists of drawing the normals and verts, it has the indicies aswell.
I am new to openGL and I somewhat have an idea of how VBO works.
This is it when I have made an attempt to add buffers to my program.
This is it without
This is my code that is currently crashing
#define GLEW_STATIC
#include <GL/glew.h
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
int main(int argc,char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("Object Loader!");
setUpArrays();
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glGenBuffers(1, &vbo);
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(normals), normals, GL_STATIC_DRAW);
GLfloat posLight0[] = {0.0f, 0.0f, -1.0f, 0.0f};
GLfloat lightColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, posLight0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
glutDisplayFunc(Draw);
glutSpecialFunc(specialKeys);
glutReshapeFunc(reshape);
glutTimerFunc(25,update,0);
glutMainLoop();
return 0;
}
This is my draw function
void Draw(void)
{
glPushMatrix();
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT,0, vertices);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, normals);
glColor3f(0.5f, 0.0f, 0.8f);
glDrawElements(GL_TRIANGLES, amountOfFaces, GL_UNSIGNED_INT, faces);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glFlush();
glutSwapBuffers();
glPopMatrix();
}
These are the only two functions that I have changed,
I've defined the unsigned int vbo and vbo2 outside.
The problem (and cause of the crash) is that your glVertexPointer should have 0 as the offset because it is relative tot the beginning of the bound buffer. (0 is a special case that treats program memory as one big buffer)
glGenBuffers(1, &vbo);
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(normals), normals, GL_STATIC_DRAW);
That is another problem; the 4th line glBindBuffer fully overrides the previous call to glBindBuffer. Or more generally; only the last glBindBuffer call is used so you never actually use vbo.
Also how are vertices and normals declared? if they are just pointers then you should replace sizeof with sizeof(*vertices)*3*amountOfFaces
Your code sample indicates that you're trying to use GLEW, but you haven't called glewInit after glutCreateWindow. You can't use OpenGL extension functions without loading their addresses first - that's exactly what GLEW do, if you don't want to mess with it manually (most likely you don't).
Your code appears to be wrong even after that, but it probably wouldn't crash. Can't say without full code of course, but
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
Don't making sense - bind one buffer, then immediately another - why is that?
I'm trying to draw a quad for a background (2D) using OpenGL 3.x+. Quads are deprecated, so the goal is to use two triangles to make a rectangle that fills the screen. It's working, but I'm not 100% clear on everything here.
Setup
GLuint positionBufferObject;
GLfloat vertexPositions[] =
{
-1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f,
};
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
I understand the vertexPositions, it's an array of vertices.
glGenBuffers() is saying, I want 1 buffer and assign id to &positionBufferObject?
glBufferData() uploads the vertexPositions to the GPU's memory; but how does it know were to upload it since I didn't give it an ID?
Draw
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
glDisableVertexAttribArray(0);
glEnableVertexAttribArray() just says I'm going to be drawing with array 0?
glDrawArrays() - what if I want to draw two vertex arrays? How does it know which ones to render? It knows that from the above command?
Not sure what glVertexAttribPointer() does?
glDrawArrays() is clear.
Clean up, I think this is right?
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &positionBufferObject);
I only do the setup/cleanup once.
Bonus points:
Is this the most effective way to render this? I read that I'm suppose to be submitting and be rendering in "batches" [?] since 3.x+ doesn't do immediate mode any more. There is also only one array, so batches won't help performance in this case, but if I had say "a very large number" of vertxArrays to draw, would it be the same process?
In setup they are storing the array id as positionBufferObject, but have it hardcoded in the rendering loop. Seems like it would get confusing after a dozen or so arrays, why isn't it good practice to use the variable instead of hardcode it?
glGenBuffers(1, &positionBufferObject); says "make a vertex buffer object, and positionBufferObject is its ID."
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject); says "positionBufferObject is now the current GL_ARRAY_BUFFER."
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW); says "upload vertexPositions to the ID currently bound to GL_ARRAY_BUFFER (which is positionBufferObject)."
glEnableVertexAttribArray(0); says "vertex attribute array 0 is now available for use."
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); says "vertex attribute array 0 is to be interpreted as consisting of groups of 4 floats."
glDrawArrays(GL_TRIANGLE_STRIP, 0, 5); says "draw a triangle strip with five indices from every enabled array."
glDisableVertexAttribArray(0); says "we're done for the time being with vertex attribute array 0."
In answer to user697111's question about multiple arrays, it's quite simple.
Each vertex attribute needs to be associated with a buffer object. Rather than specifying the buffer object with glVertexAttribPointer, the association is done through GL_ARRAY_BUFFER. When you call glVertexAttribPointer (or any gl*Pointer call), the buffer that is currently bound to GL_ARRAY_BUFFER will be used as the source for that attribute. So, consider the following:
glBindBuffer(GL_ARRAY_BUFFER, myPositionData);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, ..., 0);
glBindBuffer(GL_ARRAY_BUFFER, myColorData);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, ..., 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(...);
Attribute 0 will come from the buffer object myPositionData, and attribute 1 will come from the buffer object myColorData. The fact that I undid the binding to GL_ARRAY_BUFFER before calling glDrawArrays does not change where the data for those attributes comes from.
I'm just using the opengl SDL template with Xcode, and everything runs fine. I removed the Atlantis code, and changed the main extension to .mm, then added some testing code to drawGL. Drawing a simple triangle (using immediate mode) at this point inside drawGL gives me a white triangle, but when I add the code to draw using a vertex buffer object, i just get a black window.
Here is my VBO drawing code:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity();
GLuint buffer;
float vertices[] = {
0.0f, 1.0f, 0.0f,
-1.0f,-1.0f, 0.0f,
1.0f,-1.0f, 0.0f
};
// VBO doesn't work :(
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 9, vertices, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
Your glVertexPointer() call looks suspect for VBO usage. I think you need a BUFFER_OFFSET construct instead of the vertices pointer.