Open source Java projects: Java Binding for OpenGL (JOGL)

A low-level Java API for 3D graphics

1 2 3 4 5 6 7 8 9 Page 8
Page 8 of 9

Take pictures of a scene

JOGL's com.sun.opengl.util.Screenshot class lets you programmatically capture an OpenGL scene to a file or a buffered image. This class provides three methods for reading the scene into a buffered image, and six methods for writing the scene to a file. Three of the file-writing methods save the scene to a Targa file, and (according to their Javadoc) are the fastest methods for capturing the scene.

About Targa

Truevision Advanced Raster Graphics Adapter (TARGA), also known as Truevision Graphics Adapter (TGA), defines a file format used extensively by the animation and computer game industry for storing screen captures. Wikipedia's Truevision TGA entry has much to say about this format.

For example, Screenshot's public static void writeToTargaFile(File file, int x, int y, int width, int height, boolean alpha) method takes a screenshot of the scene in OpenGL's back buffer (unless you specify a different buffer via glReadBuffer()) and saves the screenshot in a Targa file. Pass the following arguments to this method:

  • file identifies the TARGA file that will be created to contain the screenshot
  • x identifies the starting X coordinate of the screenshot (measured from the lower-left corner of the scene)
  • y identifies the starting Y coordinate of the screenshot (measured from the lower-left corner of the scene)
  • width identifies the width of the screenshot
  • height identifies the height of the screenshot
  • alpha identifies whether (true) or not (false) the drawable's alpha channel should be saved -- the GL_EXT_abgr extension must be present when saving the alpha channel

The writeToTargaFile() method throws a GLException if the rendering context is not current (it's current when you call this method from a GLEventListener method, for example), or if some other OpenGL error occurs. This method throws an IOException if an I/O error occurs while writing to the file.

I've created a JOGLDemo4 application that demonstrates writeToTargaFile(). This application is nearly identical to JOGLDemo2, except for extra code that takes a screenshot of the most recently rendered scene and saves the result to a file named capture.tga in response to a mouse click event.

Because most of's code is identical to, I'll only focus on key differences, rather than present the complete source code -- check out this article's code archive for all of the source code. The first difference is the declaration of a mouseWasClicked field in the SceneRenderer class:

private volatile boolean mouseWasClicked;

This boolean field is marked volatile because it's accessed on the event-dispatching thread, and possibly on another thread that invokes GLEventListener's display() method. If not marked volatile, changes to mouseWasClicked's value on one thread might not be observed by the other thread. The following code fragment sets this field to true:

addMouseListener (new MouseAdapter ()
                      public void mouseClicked (MouseEvent me)
                         mouseWasClicked = true;
                         repaint ();

This code fragment installs a mouse listener via SceneRenderer's constructor. This listener responds to mouse click events by invoking repaint() to repaint the component via paintComponent(). In turn, paintComponent() causes the display() event method to be invoked. After rendering the back buffer's scene, this method executes the following code:

if (mouseWasClicked)
        int [] viewport = { 0, 0, 0, 0 };
        gl.glGetIntegerv (GL.GL_VIEWPORT, viewport, 0);
        Screenshot.writeToTargaFile (CAPTURE_FILE, viewport [0],
                                     viewport [1], viewport [2],
                                     viewport [3], false);
    catch (IOException ioe)
        System.out.println (ioe.getMessage ());

    mouseWasClicked = false;

I want to capture the back buffer's contents located within the viewport, which is why this code fragment first obtains the viewport's location and dimensions. It then saves these contents to the Targa file identified via the CAPTURE_FILE constant. I disregard the alpha channel because saving it results in a false color (but pretty) torus.

When you run JOGLDemo4, make sure to enable the OpenGL pipeline -- specify -Dsun.java2d.opengl=true or -Dsun.java2d.opengl=True on Windows platforms. Otherwise, the background sky image won't be captured. I believe this has to do with JOGL/OpenGL not rendering content to and reading content from Swing's back buffer when the OpenGL pipeline is disabled.

1 2 3 4 5 6 7 8 9 Page 8
Page 8 of 9