JOGL Draw Arrays

Calling the OpenGL drawing primitives in Java, like glVertex() and glNormal(), quickly becomes a bottleneck for rendering scenes. The function call overhead, although small, when multiplied a million times for each polygon is a problem very quickly, however, this can be overcome using glDrawArrays (commonly known as vertex arrays). Vertices, normals, colours and texture coordinates can be loaded into an IntBuffer, FloatBuffer or a DoubleBuffer (depending on what you want to use) and then sent to the rendering engine using a single glDrawArrays() function call.

import java.nio.DoubleBuffer ;
..
DoubleBuffer verticesBuffer = BufferUtil.newDoubleBuffer(3 * 3) ;
..
verticesBuffer.put(c0.x) ;
verticesBuffer.put(c0.y) ;
verticesBuffer.put(c0.z) ;
verticesBuffer.put(c1.x) ;
verticesBuffer.put(c1.y) ;
verticesBuffer.put(c1.z) ;
verticesBuffer.put(c2.x) ;
verticesBuffer.put(c2.y) ;
verticesBuffer.put(c2.z) ;
..
gl.glEnableClientState (GL.GL_VERTEX_ARRAY);
verticesBuffer.rewind();
gl.glVertexPointer(3, GL.GL_DOUBLE, 0, verticesBuffer);
gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3);

Sadly, there is still a function call overhead loading the values into the DoubleBuffer, however, this is less that the overhead of calling glVertex() multiple times. Make sure you rewind the location in the buffer using verticesBuffer.rewind() or verticesBuffer.position(0) before calling glVertexPointer() otherwise you will load the current location in the buffer into OpenGL instead of the starting location and you’ll end up only seeing a new vertices each call.

I found that loading the values into a local array and the calling the put(double[], int, int) function to load multiple values at once was much slower that calling multiple put(double) functions, even if the array was pre-allocated and reused. I could not find any way to load values into the buffers without doing it thought a function call… so if you know how to do please let me know.



// Really slow for some reason.
double array[] = new double[9] ;
array[0] = c0.x ;
array[1] = c0.y ;
..
verticesBuffer.put(array, 0, 9) ;

Rendering tip… remember to set gl.glEnable(GL.GL_NORMALIZE) when using matrixes to translating and scaling groups of vertices, otherwise the vertices normals passed to OpenGL get transformed as well, but they don’t get re-normalized, so you end up of unexpected lighting results.

Here is some good example code but make sure you add that rewind calling glColorPointer().