VBO troubles, crash when calling glDrawArrays

Hello, im trying to implement VBO’s but for 2 days i still have not found a solution.
Im sure its a simple mistake, but i cant seem to find it.
Between Init and Init buffer the buffer gets filled, all numbers are right.

The program crashes on this line:

glDrawArrays(GL_QUADS, 0, maxobjects);

Even a try / catch statement wont stop this crash, so i guess its a native crash.

Init:

    public VBO_Object(int objects){
        
        maxobjects = objects;
        stride = (3 + 3 + 2) * 4 * objects; // 3 for vertex, 3 for colour and 2 for texture coordinates. * 4 for bytes
        buffersize = (3 + 3 + 2) * objects;
        
        buffer = new float[buffersize];
    }

Init buffer

IntBuffer buffer = BufferUtils.createIntBuffer(1);
        ARBVertexBufferObject.glGenBuffersARB(buffer);
        id= buffer.get(0);

                data = BufferUtils.createFloatBuffer(buffer.length);
                data.put(buffer);
                data.flip();

Draw call:

    public void Draw(){       
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glBindBufferARB(GL_ARRAY_BUFFER_ARB, id);
        glBufferDataARB(GL_ARRAY_BUFFER_ARB, data, GL_STATIC_DRAW_ARB);
        glVertexPointer(3, GL_FLOAT, stride, /* offset **/0); // float at index 0
        glColorPointer(3, GL_FLOAT, stride, /* offset **/(3*1) << 2); // float at index 3
        glTexCoordPointer(2, GL_FLOAT, stride, /* offset **/(3*2) << 2); // float at index 6
        glDrawArrays(GL_QUADS, 0, maxobjects);

        glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }

I seee several things wrong here,

  • first you mix local variables and fields (buffer), buffer as your float data and the IntBuffer to get the BufferObject ID.
  • you upload (glBufferData) the data each frame(in the Draw command), if you are not changeing the data each frame there is no need to upload the data more then once

yes the code is not really nice, but thats becaus i tried a lot of stuff before posting it here.

glDrawArrays() expects a vertex count, not an “object” count though I guess that might just be a weird variable name.

I can’t really see anything wrong. A minor unrelated note is that GL_STATIC_DRAW_ARB is used for update-once data, so you should use GL_STREAM_DRAW_ARB since you’re updating the buffer every frame, but that’s just a hint so it shouldn’t cause a crash. Other than that I can only tell you to simplify the program (make a new test program / strip out unrelated stuff, the first one is preferred). Most likely you’re leaking some OpenGL state. Are you 100% sure that it’s crashing on that line? Maybe you call glDrawArrays() somewhere else and it crashes there? Does it crash on the first call to it or the second?

its indeed just a weird name, ill rename it to vcount.
I called it a object, because its a vertex + color + texcoord, but vcount is more clear i guess.

What you see is all what happens, so there cant be anything leaking out.
This is a new test class, so i cant make it more basic i think.

When commenting out the line it does not crash.
Also, when i call glDrawArrays(GL_QUADS, 0, 4), it does not crash, but does not show anything eighter.

Well I have run into things like this alot when using VBOs and nothing “seems” to be wrong here. Is the maxobjects in your drawArrays how many quads you want? if so you need to * that by 4. My guess is that your pointers could be wrong or your buffer itself. Make sure you are filling it properly. You also might be trying to draw with too many vertices which as caused crashes for me.

Your off sets should be 0, 12, 24. I know I followed a tut that did offsets like that and it did not work for me.

maxobjects is the amount of vertrices i want (including color and texture coords).
My fill loop (ignore weird names, its just a test class):


        obj = new VBO_Object(numstars*4);
        
        for(int i = 0; i < numstars; i ++){
            stars[i] = new BackgroundObject(this);
            stars[i].updateVBO(obj);
        }
        
        obj.create();

Then each stars fills the float array[] (for simplicity, in the future i want to write directly to the buffer)
The format is VCT (vertex, color and textcoords).
The following code works, the float array gets filled correctly, so this is probably not the problem.


        vbo.AddVertex(x, y, 0);
        vbo.AddColor(1, 1, 1);
        vbo.AddText(0, 0);
        
        vbo.AddVertex(x, y+height, 0);
        vbo.AddColor(1, 1, 1);
        vbo.AddText(0, ty);
        
        vbo.AddVertex(x+width, y+height, 0);
        vbo.AddColor(1, 1, 1);
        vbo.AddText(tx, ty);
        
        vbo.AddVertex(x+width, y, 0);
        vbo.AddColor(1, 1, 1);
        vbo.AddText(tx, 0);

Offsets should return those values, but i replaced it with your static values, still crashes.

Do i maybe need to enable some tuff with glEnable?

Can you put together a small standalone test program so we can test it? Everything looks fine to me… >_<

Your VBO is interleaved right?

Is it VCTVCTVCT or VVVCCCTTT? If it is the former then your stride is wrong. Other then that I can only agree with the broh above me. Need more code.

Oh, god, yes. Stride is the size of ONE vertex, not all vertices. It’s reading the first vertex’s data, then skipping the rest of the VBO and reading outside it —> crash.

Awsome!
Works like a charm.
I knew it would be a simple mistake.

Thanks alot guys :smiley:
Now back to my game.

One more question;

Is it better to update each entry of the floatbuffer apart, or to save these changes to the float array and load them all at once into the buffer.

it depends what you are doing, if you are changing nearly all of the data you can do the changes first your lcoal float array and then push everything to the card.

On the other hand if the data you need to update is little in comperision to the size of the hole array you can either update only a part of the gpu memory with glSubBufferData(when the data which gets updated is a chunck) or map the GPU data to a local ByteBuffer with glMapBuffer and do in that buffer all the updates.

PS: I read some time ago that the fastest way to updated the hole buffer is to first call glBufferData with the memory size you need but null as data and then call glSubBufferData for all the data you want to push to the card