views:

224

answers:

2

I'm getting a fishy error when using glDrawElements(). I'm trying to render simple primitives (mainly rectangles) to speed up drawing of text and so forth, but when I call glDrawElements() the WHOLE screen blinks black (not just my window area) for one frame or so. The next frame it turns back to the same "Windows colors" as before. And so it flickers for a couple of seconds, ending up in a message box saying

The NVIDIA OpenGL Driver encountered an unrecoverable error
and must close this application.

Error 12

Is there any setting for GL which I need to reset before calling glDrawElements()? I know it's not some dangling glEnableClientState(), I checked it (I used to have one of those, but then glDrawElements() crashed instead).

Come to think of it, it almost looks like some back buffer error... Any ideas on what to try?

A: 

Bah! Found it. When I did

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

before rendering the flickering+crashing stopped. Is this the expected behavior? Sorry for wasting time and space.

Jonas Byström
By itself, `glBindBuffer(GL_ARRAY_BUFFER, 0)` does not affect the call to glDrawElements (you have to call a gl*Pointer to capture the vbo). Re `glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)`, that has a direct impact. Where are your indices ? This calls tells the GL that they are inside your own _client_ memory, and that DrawElements is taking a pointer to that memory. If you have a non-zero value, then the GL will consider the parameter to DrawElements as an _offset_ inside the current ELEMENT_ARRAY. Using client pointers as offsets in vbos is usually a good way to crash.
Bahbar
+1  A: 

Obviously you are mixing VBO mode and VA mode. This is perfectly possible but must be use with care.

When you call:

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

This means that next time you render something with glDrawElements(..., ..., ..., x), it will use x as a pointer on the indices data, and the last call to glVertexPointer points on the vertices data.

If you don't unbind the current VBO and IBO (with the above two glBindBuffer calls), this means that when rendering with the same glDrawElements, x will be use as an offset on the indices data in the IBO, and the last call to glVertexPointer as an offset on the vertices data in the VBO.

Depending values of x and glVertexPointer you can make the driver crash because the offsets go out of bounds and/or the underlying data is of the wrong type (NaN).

So for answering your question, after drawing with VBO mode and then drawing with VA mode:

  1. unbind the current VBO
  2. unbind the current IBO
  3. specify the right vertices address with glVertexPointer
  4. specify the right indices address with glDrawElements

and then it will be fine.

Stringer Bell