LWJGL 3 vs JOGL

Disclaimer: I know this has been posted here a lot of times, and I know some of you are probably sick of seeing this, but all the times I’ve seen this type of thing posted, it’s been before the release of LWJGL 3.

I’m trying to understand the advantages of using JOGL or LWJGL. From what I know, the main difference between them is (or was) the ability of JOGL to use Java AWT or NEWT (never heard of it before). The main advantage of this was that JOGL was able to have multiple windows out of the box, whereas LWJGL 2 had the monstrous Display class, and if you wanted multiple windows with that, you had to do some hacky header-less workaround stuff with AWT.

But, with LWJGL 3 dropping all of its windowing stuff and instead using GLFW for windows and input (which it’s amazing at, gotta say (I’d like to see joystick callbacks, though)), it can now have pretty much as many windows as you want, making that a null argument for JOGL.

So, what are the differences between the two bindings, and what are the advantages and/or disadvantages of using each of them?

1 Like

LWJGL is a “static” binding, and looks very much like the raw C API.

JogAmp is an “object” binding, meaning you’ll have to pass around an instance of “gl” all over the place.

Other than that they’re functionally virtually identical. LWJGL is pretty aggressively maintained by Spasi; not sure about JogAmp but it always seems current.

Cas :slight_smile:

Please do not try to start API wars, this is a highly controversial subject. But I will try to list the LWJGL 3 pros and cons.

Pros

[] The static design is perfect for people who are coming from C/C++ background. Allows to static import functions and constants, and work just like it’s native program.
[
] Wraps GLFW, which is a perfect C library (best in my opinion, but there are others too) which provides windowing, context creation, input and event abstraction for cross platform OpenGL apps, which is also compatible with core profile OpenGL.
[] Provides bindings to the OpenAL soft library, which ensures that you can use OpenAL on any system. If it was just OpenAL bindings, it will require the user to install the OpenAL runtime through oal_inst.exe, but LWJGL prevents that with OpenAL Soft binary distribution.
[
] Provides bindings to the OpenCL, a perfect API that allows you to compute using the GPU with kernels.
[] It is the only library that I know of which currently provides bindings to the Vulkan API. Vulkan is a next generation low level cross platform graphics and compute API, which allows more low level hook into the GPU.
[
] Also provides bindings to the JEmalloc, a cross platform memory management implementation.
[] Allows you to create off screen contexts using native bindings to WGL, EGL, GLX, etc.,
[
] The bindings to STB libraries allows you to read images, decode OGG audio data, parse truetype fonts, and a lot of things too.

Cons:

[] The static design of course. A lot of people are against it as much as the people who love it. I think it is just not perfect for all times, but perfect to the design choice as the goal is to make the user think that he is using native APIs directly.
[
] AWT integration. It is not possible to integrate GLFW with AWT, but with the new JAWT bindings, things might change soon.
[] SWT integration. It is only possible up to an extent (no core OpenGL support) with Kai’s new library. Need to check it, can’t say more on that.
[
] JavaFX integration. I don’t know of any solution except any hacks.

I’m just listing the pros and cons so the OP can choose which he wants. Please do not make this controversial with why this is best and so on. Just let the OP choose.

1 Like

SWT has built-in support for OpenGL (regardless of which binding is being used). It supports JOGL and LWJGL2/3 just as well. The problem with SWT’s OpenGL at least under Windows is that no >=3.0 (respectively >=3.2 core) contexts can be created and multisampling on the window’s framebuffer is unsupported.
This is what lwjgl3-swt solves under Windows, and only under Windows, since I don’t know about the situation on other OS’es.
See the README.md for more information.

I switched from LWJGL (2) in Praxis LIVE v1 to JOGL in Praxis LIVE v2, because I switched rendering library from (a fork of) libGDX to Processing. In general I’d suggest the library support around whichever binding you choose is more important than the binding itself.

I’d also say I’m becoming more in favour of JOGL’s non-static approach <ducks for cover ;D >. This is worth a read in that context - https://jogamp.org/wiki/index.php/Why_Instance_Design I made similar choices for similar reasons in bindings for a native audio library that I maintain.

I am used to work with jogl, I wrote only a couple of simple programs in lwjgl and so I can’t really compare the two, but I can talk for jogl by my point of view.

Pro:

  • design, quoting sven, OpenGL’s implementation is not static. The wiki page nsigma linked comes from this thread. Also the wikipedia page is worth a read. This reflects in jogl being faster by about 3-5% over lwjgl based on some benchs, strictly opengl call bound, that I run a while ago (actually I plan to re-run them to see if things changed, but I need to finish first jogl-C comparison, anyway I am almost done hopefully)
  • awt, swt, swing, javafx and newt support
  • can write once and run on win, mac, linux and android (and I guess the raspberry too) using the same code
  • all the functions belonging to different opengl versions are available through the same gl object. I like passing the gl object around because I find it decreases the error window, but if you want a static approach you can grab it from the glcontext
  • you don’t have to care about path, just include the jars and be sure the native dll lie in the same place of those jar and you are done
  • offers a small util for shaders, textures, font render and math
  • the high perf newt avoids the rendering being blocked by the input listener and viceversa (on contrary of what happens with awt and company)

cons:

  • some tedious bug with the nvidia resident buffers. Somehow declaring thousand of them brings some heavy performance hitting (~80% compared to C). However the indirect version works flawless
  • direct access and buffer storage is not yet supported, that is glNamedBufferStorage
  • glMultiDrawElementsIndirectCountARB not working, since GL_PARAMETER_BUFFER_ARB is not yet recognized as a valid buffer binding point
  • rgb10a2u texture format not yet implemented
  • the texture util needs a refresh
  • vulkan not yet available

I’m obviously biased and won’t try to compare LWJGL with JogAmp or list LWJGL’s pros/cons. I’ll just say that there are differences in philosophy between the two libraries and in what they try to do and not do. JogAmp does things I wouldn’t want any library to be doing for me.

Having said that, I have to reply to this:

[quote=“elect,post:6,topic:56902”]
For those that are not aware, LWJGL performs a thread-local lookup on every call to OpenGL. It’s the only way to make the static nature of the API work. This also applies to OpenGL ES and OpenAL, but not other bindings (e.g. OpenCL or Vulkan). This may sound expensive, however:

  • It’s been like that since the first LWJGL version. If it was fast enough in 2002 and Java 1.4, it’s fast enough now.

  • You can barely measure the performance impact. It’s certainly nowhere close to a 3-5% overhead. It’s not measurable in real-world OpenGL applications and in fact it’s quite hard to measure even in micro-benchmarks (e.g. I had to use JNI methods that do nothing).

  • LWJGL 2 optimized the lookup by caching the last thread that called an OpenGL method. This has been removed in LWJGL 3, since it’s more common to have multiple threads/contexts these days. It has been replaced with an efficient (but somewhat “hacky”) O(1) lookup. java.lang.ThreadLocal is not used by default.

  • In the (very very unlikely) scenario where this lookup has a measurable performance impact for your app, you can cache OpenGL function pointers and use LWJGL’s (publicly available) JNI/“unsafe” methods. This is one of LWJGL 3’s non-obvious features: if LWJGL can do it internally, so can the user. If the user doesn’t like the way LWJGL implements something, they can replace it with a custom implementation.

  • In the (very very common) scenario where the application either a) creates a single OpenGL context only or b) all OpenGL contexts are created on the same device and with the same context creation flags, you can use [icode]Configuration.OPENGL_CAPABILITIES_STATE.set(“static”)[/icode] (or launch the JVM with -Dorg.lwjgl.opengl.capabilities=static). This completely eliminates the thread-local lookup and in fact JIT compiles to more efficient code than even JOGL’s way. This option is also available for OpenGL ES and OpenAL.

In general, LWJGL 3 has undergone extreme performance tuning. A lot of work has gone into that front the past few months and it’s one of the main reasons 3.0.0 is not released yet. The way buffers, arrays and structs are handled in LWJGL and JogAmp are completely different and LWJGL has the upper hand in all situations. If anyone has doubts or thinks otherwise, I’m willing to discuss technical details and accept any benchmarking challenge.

1 Like

Let’s try, for the sake of curiosity :stuck_out_tongue:

I just finished updating the gl3 jogl (god, one year old code looks already terrible ^^)… anyway I’ll do my best for lwjgl between today and tomorrow, in the meanwhile if you want to write it or suggest any modification don’t hesitate :wink:

run:
Lwjgl 3.0.0 build 79!
Could not read file.
C:\Users\GBarbieri\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: -1
BUILD FAILED (total time: 1 second)

What’s the problem?

Perhaps you should have printed out some useful information on line 179.

Cas :slight_smile:

Damn, I didn’t recognized it was part of my code, it was the old code I just copy/pasted somewhere, thanks

Anyway, a simple slash was missing between shader root and src

However now I get:

Exception in thread “main” java.lang.IllegalStateException: No GLCapabilities instance has been set for the current thread.

When I try to:

shaderID = GL20.glCreateShader(type);

Take in account I call glfwMakeContextCurrent(window); in the init()

Do a [icode]org.lwjgl.opengl.GL.createCapabilities();[/icode] after glfwMakeContextCurrent().

Not really, you can easily use JavaFX built-in Swing panel integration to embed GLJPanel and everything works just fine.

I’d like to chime in that I do not consider GLFW to be the gold standard of windowing systems yet. It’s lacking certain features from LWJGL 2, but most of these have been fixed last month or so. Fullscreen switching without having to recreate the window is in, but it still isn’t possible to change from normal windowed to borderless windowed for example. Also, the window icon support is very limited right now. That being said, LWJGL 3 is really frigging great in general.

I still can’t actually use it commercially, myself, because GLFW still doesn’t have buffered controller input :confused:

Cas :slight_smile:

Hmm? What is “buffered controller input”?
EDIT: This issue? https://github.com/glfw/glfw/issues/601

Yes, that exact issue.

Cas :slight_smile:

Why not just continue using JInput for Controllers with GLFW/LWJGL3? At least until GLFW controller support catches up. If you were using LWJGL2’s Controller class, you could probably just continue using that as that was just a wrapper around JInput.

Isn’t the controller code sort of mixed up with the window event handling loop though?

…besides, JInput’s broken in all sorts of other annoying ways. The trouble I’ve had getting controllers working is beyond words. I’m waiting for a one-stop decent solution to come along before I take the plunge.

Cas :slight_smile:

[quote=“theagentd,post:14,topic:56902”]
What exactly is missing? If you mean OS X icons, that’s up to the application bundling and outside GLFW’s scope.

[quote=“princec,post:15,topic:56902”]
A few points:

  • GLFW was originally supposed to be one of many windowing/input backends in LWJGL 3. Users have been pretty happy with it so an alternative has not been considered so far, but we’re open to suggestions.
  • Partial replacements is another possibility (OIS?).
  • Issues that affect commercial applications get top priority. Let us know please!