Software Development

How to start using the features in Java OpenGL

Java OpenGL (JOGL) is a wrapper library that allows a standard graphics cross-platform API called OpenGL to be used in Java. This article offers an overview of the main features of JOGL and provides some insight about how to use them.

Java OpenGL (JOGL) is a wrapper library that allows a standard graphics cross-platform API called OpenGL to be used in Java. JOGL is currently being developed by the Game Technology Group at Sun Microsystems and is the reference implementation for JSR-231 (Java Bindings for OpenGL).

Since the Java SE 6 version, Java 2D and JOGL have become interoperable, allowing JOGL to: overlay Swing components on top of OpenGL rendering; draw 3D OpenGL graphics on top of Java 2D rendering; draw Java 2D graphics on top of 3D OpenGL rendering, etc.

This article offers an overview of the main features of JOGL and provides some insight about how to use them. See Figure A, which is a screenshot of OpenGL rendering using JOGL. This is a demonstration of refraction and mirroring effects. Figure A

Figure A

JOGL design

The base OpenGL C API is accessed in JOGL via Java Native Interface (JNI) calls; this means that the underlying system must support OpenGL for JOGL to work. JOGL differs from some Java OpenGL wrapper libraries in that it merely exposes the procedural OpenGL API via methods on a few classes, rather than attempting to map OpenGL functionality onto the object-oriented programming paradigm.

The majority of the JOGL code is autogenerated from the OpenGL C header files via a conversion tool named Gluegen, which was programmed specifically to facilitate the creation of JOGL. This design decision has advantages and disadvantages.

The procedural and state machine nature of OpenGL is inconsistent with the typical method of programming under Java, which is bothersome to many programmers. The straightforward mapping of the OpenGL C API to Java methods makes conversion of existing C applications and example code much simpler. The thin layer of abstraction provided by JOGL makes runtime execution efficient; it is, however, more difficult to code than higher-level abstraction libraries like Java 3D. Because most of the code is autogenerated, changes to OpenGL can be rapidly added to JOGL.

Getting started with JOGL

In order to run any JOGL code, you will need Sun J2SDK 1.4.2 (at a minimum) and JOGL binaries. You should select your operating system, decompress the library, and ensure that it is included in your Java classpath.

To use the JOGL APIs, you need to include the JOGL package in your code. To do this, include the following import directive:

import net.java.games.jogl.*;

Then you need to create a window in which you will place all your drawings. In AWT, this is done with the new Frame("Hello World") constructor calling. Now that you have a frame/window, you need to add a JOGL GLCanvas or GLJPanel to the frame so that you may use the OpenGL bindings that JOGL provides.

Let's use a factory method to create a new GLCanvas or a new GLJPanel. Once you have a new canvas/panel, you will add it to the frame, which will cause the frame to render the canvas/panel with the rest of the window. This means you could easily add OpenGL capabilities to an existing Java GUI.

public static void main(String[] args)

{

    Frame frame = new Frame("Hello World");

    GLCanvas canvas =

GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());

    frame.add(canvas);

You will set up a few more parameters for the frame, including window size, background color, and what to do when the user closes the window (in this case, we close the entire application). Now that you have these basic parameters set up, you just have to tell the frame to render itself and start accepting user input:

    frame.setSize(300, 300);

    frame.setBackground(Color.WHITE);

    frame.addWindowListener(new WindowAdapter()

    {

        public void windowClosing(WindowEvent e)

        {

            System.exit(0);

        }

    });

    frame.show();

This provides a basic environment for JOGL/OpenGL rendering. The next step in the process is to add event handlers to your GLCanvas/GLPanel so that you can respond to user events (i.e., keyboard and mouse events) and system events (i.e., draw/render events, timers, etc.). JOGL and AWT register user actions and system requests as events. The most basic set of events that we are interested in is the set of events created by OpenGL, namely the initialize, reshape, and display window events. You can subscribe to these events by creating a net.java.games.jogl.GLEventListener. You can also subscribe to keyboard, mouse button, and mouse movement events (all from java.awt); these will allow for basic user interaction.

// make a new JOGLEventListener that is tied to this cavnas

    JoglEventListener listener = new JoglEventListener(canvas);

    canvas.addGLEventListener(listener);

    canvas.addKeyListener(listener);

    canvas.addMouseListener(listener);

    canvas.addMouseMotionListener(listener);

Next, you will create a new class called JoglEventListener, which implements all of the methods required for the four set of events to which we've subscribed. You will pass the associated GLCanvas to the constructor of the event listener. This is necessary to properly process the display/refresh event.

// necessary imports

import java.awt.event.*;

import net.java.games.jogl.*;

// a class which listens for various events raised by our GLCanvas

public class JoglEventListener implements GLEventListener, KeyListener, MouseListener, MouseMotionListener {

    // keep pointer to associated canvas so we can refresh the screen (equivalent to glutPostRedisplay())    

    private GLCanvas canvas;

    // constructor

    public JoglEventListener(GLCanvas canvas) {

        this.canvas = canvas;

    }

    // ...

    // event handler functions

    // ...

}

There are four events that you listen for when you implement GLEventListener: init(), display(), reshape(), and displayChanged().

init() is an initialization function that OpenGL/JOGL will call when setting up the graphics information when your program starts. You typically apply global settings and initialize the GL instance with your program's options.
public void init(GLDrawable gLDrawable) {

        final GL gl = glDrawable.getGL();

        final GLU glu = glDrawable.getGLU();

        gl.glMatrixMode(GL.GL_PROJECTION);

        gl.glLoadIdentity();

        glu.gluOrtho2D(-1.0f, 1.0f, -1.0f, 1.0f); // drawing square

        gl.glMatrixMode(GL.GL_MODELVIEW);

        gl.glLoadIdentity();

}
display() is very similar to java.awt.Component.paint() in that it is called each time the canvas needs to be repainted. In the code below, it draws the objects (triangle, diamond, rectangle) on the specified GLDrawable canvas.
public void display(GLDrawable gLDrawable) {

        // clear the screen

        clearScreen(glDrawable);

        // make GLObjects to represent the current state of each object

        IGLObject glDiamond = this._diamond.makeGLObject();

        IGLObject glRectangle = this._rectangle.makeGLObject();

        IGLObject glTriangle = this._triangle.makeGLObject();

        // draw the three shapes

        glDiamond.draw(glDrawable);

        glRectangle.draw(glDrawable);

        glTriangle.draw(glDrawable);

        }
reshape() is used to resize the display window. Here it is necessary to tell the canvas how to respond to the fact that the user has changed the window size -- namely, we need to change the viewport size to match.
public void reshape(GLDrawable gLDrawable, int x, int y, int width, int height) {

        final GL gl = gLDrawable.getGL();

        final GLU glu = gLDrawable.getGLU();

        gl.glViewport(0, 0, width, height); // update the viewport

    }  
displayChanged() is the last fundamental method in JOGL. In some cases, the display mode can change while the program is running. It is not actually implemented in JOGL, but it may be at some point in the future, so be sure to check the JOGL JavaDocs prior to using it.
public void displayChanged(GLDrawable gLDrawable, boolean modeChanged, boolean deviceChanged) {

        // do nothing

    }

Multithreading concerns

As stated in the Jogl - User's Guide, libraries such as the OpenGL Utility Toolkit (GLUT) use a single-threaded model for event processing. That is, when you register for a callback, your callback function will be called by the same thread that the GLUT event processor ran in.

A multithreaded approach is taken in AWT and JOGL. This means that the AWT and JOGL libraries will spawn multiple threads to handle various events: a thread for handling mouse and keyboard events; a thread for system events; a thread for display/rendering events, etc. You need to make sure that your program handles shared data in a synchronized manner.

OpenGL

After you've created your GLCanvas or GLJPanel and registered your OpenGL class to them, you can use OpenGL in a usual way like in C/C++. You get an OpenGL context object in the OpenGL init(), display(), and other methods and use it to call your API commands. (OpenGL programming and real-time 3D graphics are out of the scope of this article.)

You can see demo JOGL projects that use a lot of OpenGL at jogl-demos.dev.java.net. You should also check out the OpenGL site to gain a better understanding of how it all works.

Peter V. Mikhalenko is a Sun certified professional who works as a business and technical consultant for several top-tier investment banks.

---------------------------------------------------------------------------------------

Get Java tips in your inbox Delivered each Thursday, our free Java Developer newsletter provides insight and hands-on tips you need to unlock the full potential of this programming language. Automatically subscribe today!
2 comments
Justin James
Justin James

Sounds like knowing OpenGL is mandatory to use this, since it seems like more of a "passthrough" than an encapsulation. Is that correct? Thanks for the good article! J.Ja

peter_econ
peter_econ

Hi Justin, For advanced graphics you definitely will need to explore all OpenGL features and for that you will need to use OpenGL in full. But for simplistic graphics - just to start using OpenGL - features described in the article should be enough to start with. __ Peter

Editor's Picks