1

I'm having some difficulty getting VBOs to draw in my game. I've looked around, and checked all the common mistakes but nothing seems to get them to draw.

Here's the relevant code in order of execution:

Run Once:

public void startLWJGL() {
    try {
        Display.setParent(game.getCanvas());
        Display.create();
    } catch (LWJGLException ex) {
        System.err.print("LWJGL failed to initialize.");
        System.exit(-1);
    }

    // Initialize
    GL11.glMatrixMode(GL11.GL_PROJECTION_MATRIX);
    GL11.glLoadIdentity();
    GL11.glOrtho(0, 800, 0, 600, 1, -1); // L, R, B, T, Near, Far
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glClearColor(0.01f,0.05f,0.1f,1f);

    GL11.glDisable(GL11.GL_DEPTH_TEST);
    //GL11.glDisable(GL11.GL_BLEND);

    GL11.glViewport(0, 0, 800, 600);

    Renderer.init();
}

public static void init() {
    BALL_GEO = GL15.glGenBuffers();
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, BALL_GEO);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, makeBallGeometry(), GL15.GL_STATIC_DRAW);

    COLOR_BUF = GL15.glGenBuffers();
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, COLOR_BUF);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, makeSolidColBuffer(1f, 0f, 1f, 1f, (CIRCLE_SEGMENTS + 2)), GL15.GL_STATIC_DRAW);
}

Run Every Frame:

private void tick(long delta) {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
    Renderer.testRender();
}

    public static void testRender() {

    drawBall(new Ball(new Vector(200, 200), null, 50.0));

    // This is just test stuff that DOES work
    GL11.glColor4f(1f, 1f, 1f, 1f);
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glVertex2f(100, 100);
    GL11.glVertex2f(100, 400);
    GL11.glVertex2f(200, 400);
    GL11.glVertex2f(200, 100);
    GL11.glEnd();

    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glPushMatrix();
    //GL11.glLoadIdentity();
    GL11.glTranslatef(400f, 200f, 1f);
    GL11.glScalef(0.5f, 0.5f, 0.5f);

    GL11.glColor4f(0f, 1f, 1f, 1f);
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glVertex2f(100, 100);
    GL11.glVertex2f(100, 400);
    GL11.glVertex2f(200, 400);
    GL11.glVertex2f(200, 100);
    GL11.glEnd();

    GL11.glPopMatrix();

}

public static void drawBall(Ball o) {
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    float x = (float) o.getPos().x;
    float y = (float) o.getPos().y;
    float s = (float) o.getRadius();

    GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
    GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);

    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, BALL_GEO);
    GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, COLOR_BUF);
    GL11.glColorPointer(4, GL11.GL_FLOAT, 0, 0);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    GL11.glPushMatrix();
    //GL11.glLoadIdentity();
    GL11.glTranslatef(x, y, 0f);
    GL11.glScalef(s, s, s);

    GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, 0, (CIRCLE_SEGMENTS + 2));

    GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
    GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
    GL11.glPopMatrix();
}

In English terms, I'm rendering circles of solid colour at different sizes and locations in 2D. I tested the geometry with immediate mode and it worked fine. It is probably something really stupid, but I can't figure out what for the life of me. I was running this code on a different computer and it was spitting out 0x05 error hard crashes, but on this computer it simply doesn't render. The Ball object constructor takes a vector for its position, a velocity vector, and a radius as doubles.

EDIT: Here are the geometry and color buffer code for those asking:

private static FloatBuffer makeBallGeometry() {
    FloatBuffer buffer = BufferUtils.createFloatBuffer((CIRCLE_SEGMENTS + 2) * 3);

    float theta = 2f * (float) Math.PI / CIRCLE_SEGMENTS; // Divisions in Radians
    float tanFac = (float) Math.tan(theta); // Scalar for tangenial line
    float radFac = (float) Math.cos(theta); // Scalar for radial line
    float x = 50f;
    float y = 0f;
    float tx, ty;

    buffer.put(0f);
    buffer.put(0f);
    buffer.put(0f);
    for (int i = 0; i <= CIRCLE_SEGMENTS; i++) {
        buffer.put(x);
        buffer.put(y);
        buffer.put(0f);

        tx = -y; // Tangent
        ty = x;

        x += tx * tanFac; // Adjust over by tanFac
        y += ty * tanFac;

        x *= radFac; // Shrink by radFac
        y *= radFac;
    }

    return buffer;
}

private static FloatBuffer makeSolidColBuffer(float r, float g, float b, float a, int size) {
    FloatBuffer buffer = BufferUtils.createFloatBuffer(size * 4);
    for (int i = 0; i < size; i++) {
        buffer.put(r);
        buffer.put(g);
        buffer.put(b);
        buffer.put(a);
    }
    return buffer;
}
  • What does your geometry look like? Can you post the code for the `Ball` constructor? – user1118321 Jun 05 '14 at 01:55
  • @user1118321: The way I read the code, the `Ball` object only contains the position and radius of the ball. It's the `makeBallGeometry()` function we need to see. – Reto Koradi Jun 05 '14 at 02:49
  • `glBufferData` without a size parameter has always rubbed me the wrong way. The Java language binding computes the size of the data using the current position in your `java.nio.Buffer`, but this means if you forget to rewind (`flip`) your buffer you basically pass GL 0-bytes worth of data. Have you done that? -- More importantly, can you add the implementation of `makeBallGeometry()` and `makeSolidColBuffer()` to your question? – Andon M. Coleman Jun 05 '14 at 03:01
  • @RetoKoradi Ah yes, of course. I meant the `makeBallGeometry()` method. Good catch. – user1118321 Jun 05 '14 at 04:24
  • I added the code for generating the buffers. What is this about the flip method? I have no experience with the java.nio package so I'm probably doing something wrong there. – Switzer2007 Jun 05 '14 at 13:31

1 Answers1

1

As Andon M. Coleman pointed out, my problem was I neglected to call flip() on the buffers, and wasn't actually passing any bytes of information. I added buffer.flip() to the color and vertex buffers just before I returned them, and everything seems to be working correctly now.

  • Yeah, this is necessary because `put (...)` increments the *current* location in your buffer every time it is called. Basically it resizes the buffer and moves the current position to the end. LWJGL uses the length between the ***current*** position and the end of the buffer to determine how much data to send to GL (and where within the buffer to start copying data from). `flip (...)` sets the *current* position to the beginning of the buffer, and this allows LWJGL to send the entire buffer to GL (as opposed to sending absolutely nothing if the current position is the end). – Andon M. Coleman Jun 05 '14 at 20:03