Java 3D Implementation - OpenGL vs DirectX

This document is to track some of the nuiances of the differences between running either the OpenGL or DirectX versions of Java 3D.


Obviously the DirectX version of Java 3D is only available for Windows platforms. DirectX 7.0 is not supported on WinNT and thus isn't an option.


Our opinion is that the OpenGL implementation of Java 3D is more feature rich than the DirectX implementation. Java3D 1.2.1 DirectX implementation uses DirectX 7.0. Java 3D 1.3 will use DirectX 8.0.


With OpenGL as the primary platform independent implementation we believe Sun has put more effort into the OpenGL implementation. Currently the OpenGL implementation appears to deliver roughly 30% to 50% better frame rates. Currently laptop video drivers either only have DirectX support (if they have hardware 3D acceleration at all) or the OpenGL support is weak, thus performance on laptops is usually better using DirectX.

On NVidia video cards the OpenGL version does not use hardware anti-aliasing, but the DirectX version will do hardware anti-aliasing.


Since OpenGL was Sun's first implementation and hence Java 3D has had more history with OpenGL we believe that OpenGL should be more stable. However in bug testing a major application we found the DirectX 1.2.1 implementation to be far more stable than the OpenGL 1.2.1 implementation.



Features not supported by Java3D v1.2.1 DirectX version:

Some users are reporting "fog" does not work in the DirectX version.

The SpotLight falloff model is different between OpenGL & DirectX. In the future (Java 3D version 1.3) OpenGL will use GL_EXT_separate_specular_color to make highlights the same as DirectX if the video driver supports it.

Specular highlight in Texture mapping appears differently between OpenGL vs DirectX.


Typically resolutions below 16 bpp do not provide hardware acceleration (i.e. 256 color mode is unsupported).

Under Win98, OpenGL hardware acceleration is not supported for multiple monitors. You either need to disable one monitor in the display setting or switch to the DirectX version.

OGL: Raster is implemented using glDrawPixels() So the entire raster is passed down to the native code every frame.

DirectX: Doesn't have an API similar to glDrawPixels(), so the raster is implemented as a texture and mapped to two triangles (no Quad support in DirectX). Only when the raster changes will the texture be sent to the native code again.

So if the raster changes every frame, OGL is faster, otherwise DirectX should be faster.

As of August 2001, ATI has a reputation for poor OpenGL drivers so for ATI chipsets the DirectX version of Java 3D will probably perform better.

On NVidia video cards the OpenGL version does not use hardware anti-aliasing, but the DirectX version will do hardware anti-aliasing. So if you use anti-aliasing the DirectX version can deliver a significant perfomance advantage. Note: hardware anti-aliasing can be done in OpenGL by just forcing the video driver (not in your program, in the driver settings) to perform anti-aliasing.



Real Application Comparisions

In "Pernica" tested on November 29, 2002 on an Athlon 800 Mhz system with a GeForce 256 (driver version 30.82) running Win98SE, JDK 1.4.0 with Java 3D version 1.3. Switching between Java 3D OpenGL vs DirectX versions my performance is (at a specific location in the Pernica world that is heavy with polygons and textures):
    OpenGL - 19 to 20 fps
    DirectX - 8 fps


Interpretation of depth buffer values

For OpenGL version,
glDrawPixels(width, height, GL_DEPTH_COMPONENT, GL_FLOAT, floatData);
glReadPixels(xOffset, yoffset, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, floatData);

are used, it is up to the driver to handle the case when there is no z-buffer or it is not readable.

For D3D version using DX 7.0 (i.e. Java3D v1.2.1 )
If a device does not need a z surface, i.e. dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR then all the read/write depth component will be silently ignored.

Otherwise, the z surface is created. If during z surface lock D3D return fails, a message will printout "Fail to lock surface" with an error code and the operation will return without doing anything.

For D3D version using DX 8.0 (i.e. next Java3D 1.3 release)
The specification only allows locking the depth surface to read/write when D3DFMT_D16_LOCKABLE format is used. This means stencil buffer can't be used by specific format D3DFMT_D24S8 for features such as DecalGroup. Thus DepthComponent can't coexist with other features in Java3D that required stencil buffer. Right now the depth format available is search with stencil buffer has priority. So with the nVidia driver, if the display mode is 16 bits, then DepthComponent is supported.

If the z surface fails to get using DX function GetDepthStencilSurface(), an error message will display when -Dj3d.debug=true is used on startup. All read/write DepthComponent is ignored. The same thing happens when lock surface fails.

Further References

OpenGL Information for Microsoft Windows can be found at:

Direct3D vs. OpenGL: A Comparison -