glDrawElements() not rendering geometry

I can’t seem to use OpenGL’s glDrawElements() command which should let me send an entire array of data to be rendered at once, rather than making separate calls for each vertex in my geometry. I’ve written a demo program below which demonstrates the problem.

When the display() method calls renderSquareSingle(), a green square is correctly rendered onscreen. When it is altered to call renderSquareBuffered() instead - which should create the same geometry using buffered arrays - nothing is rendered. If anyone knows what I’m doing wrong, please let me know.

Mark McKay

import java.awt.;
import java.awt.event.
;
import java.nio.;
import java.util.
;

import net.java.games.jogl.*;

public class TestJOGLSceneFrame extends javax.swing.JFrame implements GLEventListener
{
private javax.swing.JPanel panel_gl;

public static final long serialVersionUID = 0;

GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());

public TestJOGLSceneFrame()
{
    initComponents();
    
    GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
    
    canvas.addGLEventListener(this);
    panel_gl.add(canvas, BorderLayout.CENTER);
    setSize(640, 480);
}

public void init(GLDrawable drawable) 
{
}

public void reshape(GLDrawable drawable, int x, int y, int width, int height) 
{
}

public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) 
{
}

public void display(GLDrawable drawable) 
{
    GL gl = drawable.getGL();
    
    gl.glClearColor(1, 0, 0, 1);
    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

    gl.glMatrixMode(GL.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glOrtho(0, 1, 0, 1, -1, 1);
    gl.glMatrixMode(GL.GL_MODELVIEW);
    
    gl.glColor3f(0, 1, 0);

// renderSquareSingle(gl);
renderSquareBuffered(gl);

    gl.glFlush();
}

public void renderSquareSingle(GL gl)
{
    gl.glBegin(GL.GL_QUADS);
        gl.glVertex3f(.25f, .25f, 0);
        gl.glVertex3f(.75f, .25f, 0);
        gl.glVertex3f(.75f, .75f, 0);
        gl.glVertex3f(.25f, .75f, 0);
    gl.glEnd();
}

public void renderSquareBuffered(GL gl)
{
    float[] vertex = new float[]{.25f, .25f, 0, .75f, .25f, 0, .75f, .75f, 0, .25f, .75f, 0};
    int[] indicies = new int[]{0, 1, 2, 3};
    
    FloatBuffer vertexBuf = ByteBuffer.allocateDirect(vertex.length * 4).asFloatBuffer();
    vertexBuf.put(vertex);

    IntBuffer indiciesBuf = ByteBuffer.allocateDirect(indicies.length * 4).asIntBuffer();
    indiciesBuf.put(indicies);
    
    gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexBuf);
    gl.glDrawElements(GL.GL_QUADS, indiciesBuf.limit(), GL.GL_INT, indiciesBuf);
    gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
}

private void initComponents()
{
    panel_gl = new javax.swing.JPanel();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    panel_gl.setLayout(new java.awt.BorderLayout());

    getContentPane().add(panel_gl, java.awt.BorderLayout.CENTER);

    pack();
}

public static void main(String args[])
{
    java.awt.EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            new TestJOGLSceneFrame().setVisible(true);
        }
    });
}

}

I’m not familiar with JOGL but with LWJGL you need to rewind() or flip() your buffers before passing them to such functions. LWJGL reads the buffer from its current position(), which in your case will be equal to limit(). Let me know if this is the case with JOGL.

I’ve updated the code to below, but am still getting only the background color showing: Using flip() instead of rewind doesn’t help things either.

public void renderSquareBuffered(GL gl)
{
    float[] vertex = new float[]{.25f, .25f, 0, .75f, .25f, 0, .75f, .75f, 0, .25f, .75f, 0};
    int[] indicies = new int[]{0, 1, 2, 3};
    
    FloatBuffer vertexBuf = ByteBuffer.allocateDirect(vertex.length * 4).asFloatBuffer();
    vertexBuf.put(vertex);
    vertexBuf.rewind();

    IntBuffer indiciesBuf = ByteBuffer.allocateDirect(indicies.length * 4).asIntBuffer();
    indiciesBuf.put(indicies);
    indiciesBuf.rewind();
    
    gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexBuf);
    gl.glDrawElements(GL.GL_QUADS, indiciesBuf.limit(), GL.GL_INT, indiciesBuf);
    gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
}

It looks like the line causing me trouble is the following:

    gl.glDrawElements(GL.GL_TRIANGLES, indiciesBuf.limit(), GL.GL_INT, indiciesBuf);

When I fetch gluErrorString() after executing this command, I get the message ‘invalid enumerant’. What does this mean? I’ve tried using both GL.GL_TRIANGLES and GL.GL_QUADS, but both create this error.

Mark McKay

Solved it. My problem was that I needed to allocate my FloatBuffer with net.java.games.jogl.util.BufferUtils instead of directly with NIO.

Mark McKay

Only because you didn’t set the byte-order correctly:

FloatBuffer fb = ByteBuffer.allocateDirect(elements * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

So you can still do it in your own code. You could check the sourcecode of the BufferUtils class.