Skip to content
Martin Prout edited this page May 20, 2015 · 3 revisions

Using the low-level OpenGL functions is for advanced users only!

Generally, this should be only considered a last-ditch way to get at a particular GL-specific feature. It can make your code incompatible with everything else (such as future versions of Processing or other 3D renderers) and will confuse the hell outta people when you post your code to the web. Again, if this works for you great, but if not, we aren't responsible. If you want to write code for Java and JOGL, then find yourself a good Java IDE and get JOGL installed, Processing is probably not the way to do it because that's the kind of confusing mess we're trying to insulate you from.

Due to the changes in the OpenGL renderer from Processing 1.x to 2.x, the way to access the low-level functions is different

Processing 1.x

To get access to the GL object, use the following:

GL gl = ((PGraphicsOpenGL)g).gl;

This will give you JOGL's GL object that talks directly to OpenGL and will let you make OpenGL calls directly. Again, this is not supported, in the sense that if you get weird problems with a GL-based sketch that uses this method, you're on your own. Because most of the work in drawing is handled by Processing, most OpenGL calls will not work, because most things won't be set up properly. Therefore, using the GL object may only be useful for tweaking obscure OpenGL parameters. Another option for talking directly to OpenGL in release 0116 and later is to use the beginGL() and endGL() methods. These were added against my better judgment, and handle setting up the camera matrices (though still no lighting or other parameters). Many features still will not work, but it opens up lots of control for geometry. All the above caveats about "don't cry when it breaks" apply.

import javax.media.opengl.*;
import processing.opengl.*;
 
float a; 
 
void setup() {
  size(800, 600, OPENGL);
}
 
void draw() {
  background(255);
 
  PGraphicsOpenGL pgl = (PGraphicsOpenGL) g;  // g may change
  GL gl = pgl.beginGL();  // always use the GL object returned by beginGL
 
  // Do some things with gl.xxx functions here.
  // For example, the program above is translated into:
  gl.glColor4f(0.7, 0.7, 0.7, 0.8);
  gl.glTranslatef(width/2, height/2, 0);
  gl.glRotatef(a, 1, 0, 0);
  gl.glRotatef(a*2, 0, 1, 0);
  gl.glRectf(-200, -200, 200, 200);
  gl.glRotatef(90, 1, 0, 0);
  gl.glRectf(-200, -200, 200, 200);
 
  pgl.endGL();
 
  a += 0.5;
}

Processing 2.x

The OpenGL renderer in Processing 2.x uses JOGL 2.x, which introduced the concept of profiles to access different versions of the GL API. The GL2 profile is probably the one you want to use if you were working with low-level GL in Processing 1.x, since it offers backwards compatibility with Open GL 1.x (i.e.: fixed function pipeline), while supporting shaders and other more recent functionality. To access the GL2 profile, you would do:

PGraphicsOpenGL pg = (PGraphicsOpenGL)g;
PGL pgl = beginPGL();  
gl2 = ((PJOGL)pgl).gl.getGL2();

In a similar fashion to Processing 1.x, you need to enclose the GL calls between beginPGL() and endPGL():

import javax.media.opengl.GL2;
 
float a;

PGraphicsOpenGL pg; 
PGL pgl;
GL2 gl;

float[] projMatrix;
float[] mvMatrix;
 
void setup() {
  size(800, 600, OPENGL);
  projMatrix = new float[16];
  mvMatrix = new float[16]; 
}
 
void draw() {
  background(255);
 
  pg = (PGraphicsOpenGL)g;
  pgl = beginPGL();  
  gl = ((PJOGL)pgl).gl.getGL2();
  
  copyMatrices();  
  // Do some things with gl.xxx functions here.
  // For example, the program above is translated into:
  gl.glColor4f(0.7, 0.7, 0.7, 0.8);
  gl.glTranslatef(width/2, height/2, 0);
  gl.glRotatef(a, 1, 0, 0);
  gl.glRotatef(a*2, 0, 1, 0);
  gl.glRectf(-200, -200, 200, 200);
  gl.glRotatef(90, 1, 0, 0);
  gl.glRectf(-200, -200, 200, 200);
 
  endPGL();
 
  a += 0.5;
}

// Copies the current projection and modelview matrices from Processing to OpenGL
// It needs to be done explicitly, otherwise GL will use the identity matrices by
// default!
void copyMatrices() {
  PGraphicsOpenGL pg = (PGraphicsOpenGL)g;
 
  gl.glMatrixMode(GL2.GL_PROJECTION);
  projMatrix[0] = pg.projection.m00;
  projMatrix[1] = pg.projection.m10;
  projMatrix[2] = pg.projection.m20;
  projMatrix[3] = pg.projection.m30;
 
  projMatrix[4] = pg.projection.m01;
  projMatrix[5] = pg.projection.m11;
  projMatrix[6] = pg.projection.m21;
  projMatrix[7] = pg.projection.m31;
 
  projMatrix[8] = pg.projection.m02;
  projMatrix[9] = pg.projection.m12;
  projMatrix[10] = pg.projection.m22;
  projMatrix[11] = pg.projection.m32;
 
  projMatrix[12] = pg.projection.m03;
  projMatrix[13] = pg.projection.m13;
  projMatrix[14] = pg.projection.m23;
  projMatrix[15] = pg.projection.m33;
 
  gl.glLoadMatrixf(projMatrix, 0);
 
  gl.glMatrixMode(GL2.GL_MODELVIEW);
  mvMatrix[0] = pg.modelview.m00;
  mvMatrix[1] = pg.modelview.m10;
  mvMatrix[2] = pg.modelview.m20;
  mvMatrix[3] = pg.modelview.m30;
 
  mvMatrix[4] = pg.modelview.m01;
  mvMatrix[5] = pg.modelview.m11;
  mvMatrix[6] = pg.modelview.m21;
  mvMatrix[7] = pg.modelview.m31;
 
  mvMatrix[8] = pg.modelview.m02;
  mvMatrix[9] = pg.modelview.m12;
  mvMatrix[10] = pg.modelview.m22;
  mvMatrix[11] = pg.modelview.m32;
 
  mvMatrix[12] = pg.modelview.m03;
  mvMatrix[13] = pg.modelview.m13;
  mvMatrix[14] = pg.modelview.m23;
  mvMatrix[15] = pg.modelview.m33;
  gl.glLoadMatrixf(mvMatrix, 0);
}

Below you have a slightly more advanced example to render 1,000,000 points using Vertex Arrays in Processing 2.x

import javax.media.opengl.GL2;
import java.nio.*;
 
// let's try 1,000,000 points
int numPoints = 1000000;
 
// pan, zoom and rotate
float tx = 0, ty = 0;
float sc = 1;
float a = 0.0;
 
FloatBuffer vbuffer;
FloatBuffer cbuffer;
float[] projMatrix;
float[] mvMatrix;
 
PGraphicsOpenGL pg; 
PGL pgl;
GL2 gl2;

void setup() {
  size(displayWidth/2, displayHeight/2, OPENGL); 
  smooth();
 
  pg = (PGraphicsOpenGL)g;
  pgl = beginPGL();  
  gl2 = ((PJOGL)pgl).gl.getGL2();
 
  int vSize = (numPoints * 2);
  int cSize = (numPoints * 3);
  vSize = vSize << 2;
  cSize = cSize << 2;
 
  vbuffer = ByteBuffer.allocateDirect(vSize).order(ByteOrder.nativeOrder()).asFloatBuffer();
  cbuffer = ByteBuffer.allocateDirect(cSize).order(ByteOrder.nativeOrder()).asFloatBuffer();
  for (int i = 0; i < numPoints; i++) {
    // random x,y
    vbuffer.put(random(width));
    vbuffer.put(random(height));
    // random r,g,b
    cbuffer.put(random(1.0));
    cbuffer.put(random(1.0));
    cbuffer.put(random(1.0));
  }
  vbuffer.rewind();
  cbuffer.rewind();
 
  gl2.glEnableClientState(GL2.GL_VERTEX_ARRAY);
  gl2.glVertexPointer(2, GL2.GL_FLOAT, 0, vbuffer);
 
  gl2.glEnableClientState(GL2.GL_COLOR_ARRAY);
  gl2.glColorPointer(3, GL2.GL_FLOAT, 0, cbuffer);
 
  pg.endPGL();
 
  projMatrix = new float[16];
  mvMatrix = new float[16]; 
}
 
void draw() {
  background(0);
 
  pgl = beginPGL();  
  gl2 = ((PJOGL)pgl).gl.getGL2();
 
  copyMatrices();
 
  gl2.glPushMatrix();
  gl2.glTranslatef(width/2, height/2, 0);
  gl2.glScalef(sc,sc,sc);
  gl2.glRotatef(a, 0.0, 0.0, 1.0);
  gl2.glTranslatef(-width/2, -height/2, 0);
  gl2.glTranslatef(tx,ty, 0);
 
  gl2.glPointSize(2.0);
 
  gl2.glDrawArrays(GL2.GL_POINTS, 0, numPoints);
 
  gl2.glPopMatrix();
 
  endPGL();
}
 
void mouseDragged() {
  float dx = (mouseX - pmouseX) / sc;
  float dy = (mouseY - pmouseY) / sc;
  float angle = radians(-a);
  float rx = cos(angle)*dx - sin(angle)*dy;
  float ry = sin(angle)*dx + cos(angle)*dy;
  tx += rx;
  ty += ry;
}

void copyMatrices() {
  gl2.glMatrixMode(GL2.GL_PROJECTION);
  
  projMatrix[0] = pg.projection.m00;
  projMatrix[1] = pg.projection.m10;
  projMatrix[2] = pg.projection.m20;
  projMatrix[3] = pg.projection.m30;
 
  projMatrix[4] = pg.projection.m01;
  projMatrix[5] = pg.projection.m11;
  projMatrix[6] = pg.projection.m21;
  projMatrix[7] = pg.projection.m31;
 
  projMatrix[8] = pg.projection.m02;
  projMatrix[9] = pg.projection.m12;
  projMatrix[10] = pg.projection.m22;
  projMatrix[11] = pg.projection.m32;
 
  projMatrix[12] = pg.projection.m03;
  projMatrix[13] = pg.projection.m13;
  projMatrix[14] = pg.projection.m23;
  projMatrix[15] = pg.projection.m33;
 
  gl2.glLoadMatrixf(projMatrix, 0);
 
  gl2.glMatrixMode(GL2.GL_MODELVIEW);
  mvMatrix[0] = pg.modelview.m00;
  mvMatrix[1] = pg.modelview.m10;
  mvMatrix[2] = pg.modelview.m20;
  mvMatrix[3] = pg.modelview.m30;
 
  mvMatrix[4] = pg.modelview.m01;
  mvMatrix[5] = pg.modelview.m11;
  mvMatrix[6] = pg.modelview.m21;
  mvMatrix[7] = pg.modelview.m31;
 
  mvMatrix[8] = pg.modelview.m02;
  mvMatrix[9] = pg.modelview.m12;
  mvMatrix[10] = pg.modelview.m22;
  mvMatrix[11] = pg.modelview.m32;
 
  mvMatrix[12] = pg.modelview.m03;
  mvMatrix[13] = pg.modelview.m13;
  mvMatrix[14] = pg.modelview.m23;
  mvMatrix[15] = pg.modelview.m33;
  gl2.glLoadMatrixf(mvMatrix, 0);
}

Processing 3.x

All of the above should apply for Processing 3.x up to the 3.0a5 release but also after 3.0a8 release. (For releases 3.0a6 to 3.0a7 we replaced JOGL by LWJGL). To be updated...

Clone this wiki locally