I have some old code that uses OpenGL 1.1 that is mysteriously segfaulting. One place where I might be going wrong is that I free() an array after providing it to glNormalPointer. Is that permitted, or does OpenGL require the memory at that pointer to stick around? I had been assuming that the data was copied.
double vertices[] = { ... };
double *normals = (double *)malloc(sizeof(vertices));
CalcNormals(vertices, normals, num_vertices); // Calculate the normal vectors.
GLuint my_display_list = glGenLists(1);
glNewList(my_display_list, GL_COMPILE);
glVertexPointer(3, GL_DOUBLE, 0, vertices);
glNormalPointer(GL_DOUBLE, 0, normals);
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
glEndList();
free(normals); // Is this permitted?
// ...
glCallList(winglist);
EDIT 1: I noticed a few references that say that glNormalPointer and other "client state commands" cannot be included in a display list. I guess in this case, inclusion of glVertexPointer and glNormalPointer between glNewList and glEndList probably does no harm, but I might as well move them up, to occur before glNewList. It's the call to glDrawArrays that's really being recorded in the display list, right?
EDIT 2: I tried calling memset(normals, 0, sizeof(vertices)) to forcefully clear the normals buffer before freeing it, to make a use-after-free situation more obvious. Because the scene still draws properly, I conclude that the normals buffer that I allocate is not being used after the call to glDrawArrays.
I noticed a few references that say that glNormalPointer and other "client state commands" cannot be included in a display list.
No, it says that they aren't included in the display list. Which is true; they aren't.
But their effects can be.
The gl*Pointer commands retain the pointer well after their the command executes. That is, the pointer isn't used yet. It only gets read from when you invoke a rendering command using that pointer as client state.
The behavior of glDraw* calls with client-side vertex arrays is defined in terms of a sequence of calls to glArrayElement within a glBegin/End pair, which itself is defined in terms of a series of call to glVertex/Normal/etc, using values read from the vertex arrays. Display lists record those glVertex/etc calls into the display list itself. Thus, while recording to a display list, when you render with client-side vertex arrays you will record the contents of the arrays into the display list.
You can free the client memory only if you don't try to read from it again.
Related
I have a working implementation of this technique for view frustum culling of instanced geometry. The gist of the technique is that we use a vertex shader to check if the bounds of an object lie within the view frustum, and if they do we output the position of that object, using a transform feedback buffer and a geometry shader, to a texture. We can then, during an actual rendering pass, use that texture, along with a query of how many positions we emitted, to acquire the relevant position data for the object we're rendering, and number of draws to specify in our call to glDrawElementsInstanced. One difference between what I do, and what the article does, is that I emit a full transformation matrix, rather than a simple position vector, to the texture, but I doubt that has any bearing on my problem.
The actual problem: Currently I have this setup so that, for each object type being rendered (i.e. tree, box, rock, whatever), the actual rendering pass follows immediately upon the frustum cull rendering pass. This works, and gives the intended results. What I want to do instead, however, is to go over all my drawcommands and do all the frustum culling for the various objects first, and only thereafter do all the actual rendering, to avoid a bunch of unnecessary state changes (i.e. switching back and forth between shader programs). When I do this, however, I encounter the problem that previously established textures -- the ones I use for reading positions from during the actual rendering passes -- all seem to be overwritten by the latest call to the frustum culling function, meaning that all textures established seemingly contain only the position information from the last frustum cull call.
For example: I render, in order, 4 trees, 10 boxes and 3 rocks, and what I will see instead is a tree, a box, and a rock, at all the (three) positions where I would expect only the 3 rocks to be. I cannot for the life of me figure out why this is, because I quite clearly bind new buffers and textures to the TRANSFORM_FEEDBACK_BUFFER every time I call the function. Why are the previously used textures still receiving the new data from the latest call?
Code, in C, for the frustum culling function:
void fcullidraw(drawcommand *tar) {
/* printf("Fculling %s\n", tar->res->name); */
mesh *rmesh = &tar->res->amod->meshes[0];
/* glDeleteTextures(1, &rmesh->ctex); */
if(rmesh->ctbuf == 0)
glGenBuffers(1, &rmesh->ctbuf);
glBindBuffer(GL_TEXTURE_BUFFER, rmesh->ctbuf);
glBufferData(GL_TEXTURE_BUFFER, sizeof(instancedata) * tar->nodraws, NULL, GL_DYNAMIC_COPY);
if(rmesh->ctex == 0)
glGenTextures(1, &rmesh->ctex);
glBindTexture(GL_TEXTURE_BUFFER, rmesh->ctex);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, rmesh->ctbuf);
if(rmesh->cquery == 0)
glGenQueries(1, &rmesh->cquery);
checkactiveshader(tar->tar, findshader("icull"));
glEnable(GL_RASTERIZER_DISCARD);
glUniform1f(activeshader->radius, tar->res->amesh->bbox.radius);
glUniform3fv(activeshader->extent, 1, (const GLfloat*)&tar->res->amesh->bbox.ext);
glUniform3fv(activeshader->cp, 1, (const GLfloat*)&tar->res->amesh->bbox.cp);
glBindVertexArray(tar->res->amod->meshes[0].vao);
glBindBuffer(GL_ARRAY_BUFFER, tar->res->amod->meshes[0].posarray);
glBufferData(GL_ARRAY_BUFFER, sizeof(mat4_t) * tar->nodraws, tar->posarray, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, rmesh->ctbuf);
glBeginTransformFeedback(GL_POINTS);
glBeginQuery(GL_PRIMITIVES_GENERATED, rmesh->cquery);
glDrawArrays(GL_POINTS, 0, tar->nodraws);
glEndQuery(GL_PRIMITIVES_GENERATED);
glEndTransformFeedback();
glDisable(GL_RASTERIZER_DISCARD);
glGetQueryObjectuiv(rmesh->cquery, GL_QUERY_RESULT, &rmesh->visibleinstances);
}
tar and rmesh obviously vary between each call to this function. Do note that I have left in a few lines of comments here containing code to delete the buffers and textures between each rendering cycle, rather than simply overwriting them, but using that code instead has no effect on the error mode.
I'm stumped. I feel that the textures and buffers are well defined and clearly kept separate, so I do not understand how the textures from previous calls to fcullidraw are somehow still bound to and being overwritten by the TransformFeedback, if that is indeed what is happening, and it certainly seems to be, because the earlier objects will read in the entire transformation matrix of the rock quite neatly, with the "right" rotation, translation, and everything.
The article linked does do the operations in the order I want to do them -- i.e. first repeated frustum culls, and then repeated rendering -- and I'm not sure I see what I do differently. Might be some small and obvious thing, and I might be an idiot, but in that case I'd love to know why and how I am that.
EDIT: I pushed on and updated my implementation with a refinement of the original technique, suggested here, which gets rid of the writing-to-texture method altogether, in favor of instead simply writing to a buffer bound to the VAO, and set to update once per rendered instance with a VertexAttribDivisor. This method looks at lot cleaner on the whole, and incidentally had the additional side effect of not having my original problem at all, as I'm no longer writing to and uploading textures. This is, thus, no longer a practical problem for me, but the answer to the theoretical question does still elude me, so if anyone has ideas I'm still all ears.
I've run into a bit of a confusing problem with OpenGL, it's rather simple but I've failed to find any directly related information.
What I'm trying to do
I'm creating several new textures every frame, and right after creation I bind them, use them for drawing, and then delete them right after.
The Problem
If I delete every texture right after it was used, the last one to be drawn replaces the previous ones(but their different geometry works as it should). If I batch my deletions after all drawing has been done, it works as expected, but if I do any draw calls at all after deleting the textures, the texture used in the last drawcall replaces the old ones(which could be some common permanent sprite texture).
Results from debugging
I've tried using glFlush(), which didn't seem to do anything at all, not deleting the textures at all gives the correct behaviour, and also not drawing anything at all between deleting the textures and calling SwapBuffers() works.
Code
This is not what my code looks like, but this is what the relevant parts boil down to:
int Tex1, Tex2, Tex3;
glGenTextures(1, &Tex1);
glBindTexture(GL_TEXTURE_2D, Tex1);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex1
glGenTextures(1, &Tex2);
glBindTexture(GL_TEXTURE_2D, Tex2);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex2
// I delete some textures here.
glDeleteTextures(1, &Tex1);
glDeleteTextures(1, &Tex2);
// If I comment out this section, everything works correctly
// If I leave it in, this texture replaces Tex1 and Tex2, but
// the geometry is correct for each geometry batch.
glGenTextures(1, &Tex3);
glBindTexture(GL_TEXTURE_2D, Tex3);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex3
glDeleteTextures(1, &Tex3);
// ...
SwapBuffers();
I suspect this might have something to do with OpenGL buffering my draw calls,
and by the time they are actually processed the textures are deleted? It doesn't really make sense to me though, why would drawing something else after deleting the previous textures cause this behaviour?
More context
The generated textures are text strings, that may or may not change each frame, right now I create new textures for each string each frame and then render the texture and discard it right after. The bitmap data is generated with Windows GDI.
I'm not really looking for advice on efficiency, ideally I want an answer that can quote the documentation on the expected/correct behaviour for rendering using temporary textures like this, as well as possible common gotchas with this approach.
The expected behavior is clear. You can delete the objects as soon as you are done using them. In your case, after you made the draw calls that use the textures, you can call glDeleteTextures() on those textures. No additional precautions are required from your side.
Under the hood, OpenGL will typically execute the draw calls asynchronously. So the texture will still be used after the draw call returns. But that's not your problem. The driver is responsible for tracking and managing the lifetime of objects to keep them around until they are not used anymore.
The clearest expression of this I found in the spec is on page 28 of the OpenGL 4.5 spec:
If an object is deleted while it is currently in use by a GL context, its name is immediately marked as unused, and some types of objects are automatically unbound from binding points in the current context, as described in section 5.1.2. However, the actual underlying object is not deleted until it is no longer in use.
In your code, this means that the driver can't delete the textures until the GPU completed the draw call using the texture.
Why that doesn't work in your case is hard to tell. One possibility is always that something in your code unintentionally deletes the texture earlier than it should be. With complex software architectures, that happens much more easily than you might think. For example, a really popular cause is that people wrap OpenGL objects in C++ classes, and let those C++ objects go out of scope while the underlying OpenGL object is still in use.
So you should definitely double check (for example by using debug breakpoints or logging) that no code that deletes textures is invoked at unexpected times.
The other option is a driver bug. While object lifetime management is not entirely trivial, it is so critical that it's hard to imagine it being broken for a very basic case. But it's certainly possible, and more or less likely depending on vendor and platform.
As a workaround, you could try not deleting the texture objects, and only specifying new data (using glTexImage2D()) for the same objects instead. If the texture size does not change, it would probably be more efficient to only replace the data with glTexSubImage2D() anyway.
rather than post lots of code, I will phrase this question intuitively. I hope you understand what I am getting at.
I am making a game and in the code I have a model class that loads a model and sets up the VBO for it.
In the loading function, it generates a new VBO ID and loads the vertex data from a file into that buffer by binding it etc. (This works fine)
At the beginning of the program I make one model object and load a .obj file.
In the render function, I simply call the DrawArrays() function (with the neccessary extra stuff) and as I said, everything works fine as the model appears on the screen with no problems.
The problem however, is when I make two model objects at the beginning of the program and load a different .obj file into each one.
The issue is that when I play, only the second model is drawn on screen.
The problem is because I don't properly understand how VBO's work.
This is how I "think" VBO's work.
You can generate as many VBO ID's as you want.
You can bind each ID to make it the active buffer.
You can load vertex data into that buffer.
You now effectively have many different ID's each referring to a "set of vertex data".
By calling the DrawArray function it draws every buffer you have generated (effectively displaying all your models on screen)
Now I know this is wrong because in my limited understanding I can't see how I could turn models on/off. But no matter how many tutorials I look at I can't answer this question because they all focus on displaying that ONE FIRST VBO, which incidentally I can do.
So... if that made sense, could anyone enlighten me?
You're doing it mostly right, but the drawing command does not draw every buffer you have generated. If you want to draw 2 objects with data in different buffers, you'll have to issue 2 drawing commands.
Let me explain, based on how I do it:
You create buffers using glGenBuffers. Before you can use a buffer, you have to "bind" it, that is, make it active using glBindBuffer. When a buffer is active, you can do stuff with it (populate with data for example). Note that there are different bind targets, so you can, for example, have one active array buffer (for vertex data) and one active element array buffer (for index data).
When you want to draw stuff, you have to specify what exactly you want to draw (I'll assume now that you're using your own shader) Usually you specify at least your vertex data and index data. To do this, you first bind your buffer with your vertex data (as an array buffer), then call glVertexAttribPointer with you attribute id. This tells OpenGL that the bound buffer is now the source for the current attribute. Then, you bind your index buffer as the element array buffer and call glDrawElements (not sure how glDrawArrays would work here).
You cannot use multiple VBOs at once for the same attribute - the call to bind another buffer just overwrites the previous call and makes the second buffer active, which, I assume, is why only your second object gets drawn.
You can also use VAOs to simplify the drawing - basically you assign an id to binding commands, then you can execute them with one line (think display lists).
So, my loading (of one object) looks like this:
Create buffers (let's say buffer 1 is for vertex data, buffer 2 for index data).
Bind buffer 1 as an array buffer.
Fill buffer with vertex data.
Repeat 2 and 3 for buffer 2 as element array buffer and index data, respectively.
And my drawing (again, of one object):
Bind buffer 1 as an array buffer.
Use glVertexAttribPointer to specify that this buffer goes to a specific attribute.
Bind buffer 2 as an element array buffer.
Call DrawElements
For the second object, you have to repeat everything.
Follow these steps to render your models, assuming model1 vertices are stored in vertexBuffer and model2 vertices in vertexBuffer2:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, <no. of vert>);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer2);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, <no. of vert>);
//swap buffers depending on your windowing toolkit
Make sure to not perform glClear in the middle of the two model renders.
All the best!
what you want to do is set the vertexArrayAttribute back to the first object data before each call to drawArrays
the draw arrays function uses the bindings stored in the VAO to find the data needed to render everything
so to render 2 models you create a second VAO bind it and call glVertexAttribPointer as needed. for drawing you bind the VAO and call drawArrays for each model
I'm converting my OpenGL 2 program to OpenGL 3, one small step at a time. The current step is to get rid of immediate mode in favor of VBOs. I'm stumbling on the proper placement of all the VBO state management calls.
Let's assume I'm going to have a bunch of objects, each with its own VBOs for vertex and element data. Each object has a load function that sets up its VBOs and loads data into them; and it has a draw function that binds its VBOs and issues the appropriate draw command. To keep the objects from interfering with each other, my main loop should call PushClientAttrib(CLIENT_VERTEX_ARRAY_BIT) before either draw or load is called, correct? (And of course PopClientAttrib() after.)
When I push/pop that state to protect my load function, the object doesn't get drawn. It seems like there's some state I need to (re)set in my draw function, but I can't figure out what it could be.
Here's code to add a new object e to the scene, letting it call its load function:
gl.PushClientAttrib(gl.CLIENT_VERTEX_ARRAY_BIT)
e.SceneAdded()
gl.PopClientAttrib()
And here's how I call each object's draw function:
gl.PushClientAttrib(gl.CLIENT_VERTEX_ARRAY_BIT)
gl.PushMatrix()
p.Paint()
gl.PopMatrix()
gl.PopClientAttrib()
Here's the object's load function:
// Make the vertex & texture data known to GL.
gl.GenBuffers(1, &vboId)
gl.BindBuffer(gl.ARRAY_BUFFER, vboId)
gl.BufferData(gl.ARRAY_BUFFER,
gl.Sizeiptr(unsafe.Sizeof(gldata[0])*uintptr(len(gldata))),
gl.Pointer(&gldata[0].x), gl.STATIC_DRAW)
gl.VertexPointer(3, gl.DOUBLE, gl.Sizei(unsafe.Sizeof(gldata[0])),
gl.Pointer(unsafe.Offsetof(gldata[0].x)))
gl.TexCoordPointer(2, gl.DOUBLE, gl.Sizei(unsafe.Sizeof(gldata[0])),
gl.Pointer(unsafe.Offsetof(gldata[0].s)))
// Make the index data known to GL.
gl.GenBuffers(1, &iboId)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboId)
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER,
gl.Sizeiptr(unsafe.Sizeof(sd.indices[0])*uintptr(len(sd.indices))),
gl.Pointer(&sd.indices[0]), gl.STATIC_DRAW)
Finally, here's the object's draw function:
func draw() {
gl.BindBuffer(gl.ARRAY_BUFFER, vboId)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, iboId)
gl.EnableClientState(gl.VERTEX_ARRAY)
gl.EnableClientState(gl.TEXTURE_COORD_ARRAY)
gl.DrawElements(gl.TRIANGLES, indexcount, gl.UNSIGNED_SHORT, nil)
}
Just to be clear, if I move the two EnableClientState calls from draw to load, and if I don't protect load with PushClientState, everything works fine.
I'm converting my OpenGL 2 program to OpenGL 3
Well then the following
To keep the objects from interfering with each other, my main loop should call PushClientAttrib(CLIENT_VERTEX_ARRAY_BIT) before either draw or load is called, correct? (And of course PopClientAttrib() after.)
is not a sane approach. glPushAttrib and glPopAttrib are deprecated, i.e. should not be used in OpenGL-3 program.
Also OpenGL vertex arrays don't use glVertexPointer the use glVertexAttribPointer. Attribute pointer state can be managed (and I recommend that) in a Vertex Array Object, which you can bind/unbind.
BTW: When you wrote for OpenGL-2, why did you use immediate mode in the first place? Use of immediate mode is discouraged ever since OpenGL-1.1, when vertex arrays had been introduced. And already with OpenGL-2 it was considered to remove immediate mode.
The answer to the question I actually asked is that gl.VertexPointer() and friends need to be called from the object's draw function. My main loop is pushing and popping all state related to client vertices, so of course that gets lost.
The question I implied is, "How can I convert my old, GL2 program to new, GL3 code?" That's answered very elegantly here.
I am trying to setup a simple function which will make it a lot easier for me to texture map geometry in OpenGL, but for some reason when I'm trying to make a skybox, I am getting a white box instead of the texture mapped geometry. I think that the problemed code lies within the following:
void MapTexture (char *File, int TextNum) {
if (!TextureImage[TextNum]){
TextureImage[TextNum]=auxDIBImageLoad(File);
glGenTextures(1, &texture[TextNum]);
glBindTexture(GL_TEXTURE_2D, texture[TextNum]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[TextNum]->sizeX, TextureImage[TextNum]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[TextNum]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture[TextNum]);
//glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[TextNum]->sizeX, TextureImage[TextNum]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[TextNum]->data);
//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
}
The big thing I don't understand is for some reason the glBindTexture() must come between glGenTextures() and glTexImage2D. If I place it anywhere else, it screws everything up. What could be causing this problem? Sorry if it's something simple, I'm brand new to openGL.
Below is a screenshot of the whitebox I am talking about:
+++++++++++++++++++++++++++++++
EDIT
+++++++++++++++++++++++++++++++
After playing around with the code a bit more, i realized that if I added glTexImage2D() and glTexParameteri()after the last glBindTexture() then all the textures load. Why is it that without these two lines most textures would load, and yet there are a few that would not, and why do I have to call glTexImage() for every frame, but only for a few textures?
Yes, order is definitely important.
glGenTexture creates a texture name.
glBindTexture takes the texture name generated by glGenTexture, so it can't be run before glGenTexture.
glTexImage2D uploads data to the currently bound texture, so it can't be run before glBindTexture.
The client-side interface to OpenGL is a Big Giant Squggly State Machine. There are an enormous number of parameters and flags that you can change, and you have to be scrupulous to always leave OpenGL in the right state. This usually means popping matrices you push and restoring flags that you modify (at least in OpenGL 1.x).
OpenGL is a state machine, which means that you can pull its levers, turn its knobs, and it will keep those settings, until you change them actively.
However it also manages it's persistent data in objects. Such objects are something abstract, and must not be confused with objects seen on the screen!
Now to the outside OpenGL identifies objects by their so called name, a numerical ID. You create a (list of) name(s) – but not the object(s)! – with glGenTextures for texture objects, which are such a kind of OpenGL object.
To maniupulate such an object, OpenGL must first be put into a state that all the following calls to manipulate such objects of that type happen to one particular object. This is done with glBindTexture. After calling glBindTexture all the following calls that manipulate textures happen to that one texture object you've just bound. If the object didn't exist previously, it is created if a new assigned object name is bound for the first time.
Now OpenGL uses that particular object.
glTexImage2D is just one of several functions to maniuplate the data of the currently bound textures.
Otherwise your function points into the right direction. OpenGL has no real initialization phase, you just do things as you go along. And it makes sense to defer loading of data until you need it. But it also makes sense to have multiple iterations over the lists of objects before you actually draw a frame. One of the preparations should be, that you iterate over all objects (now not OpenGL but your's) to test if the data's already loaded. If a significant amount of data's still missing, draw a loading screen instead, so that the user doesn't get the impression your program hangs. Maybe even carry out lengthy loading operations in a separate thread, but with OpenGL this requires some precautions.