JOGL design issues

Hi all

I’ve been developing a 3D engine which currently has a LWJGL implementation. I would like to migrate to JOGL as it seems to be more Java-like, particularly with the JSR in mind.

However I was somewhat surprised by the constraints that JOGL seems to put on the architecture of my engine:

  1. Is a GLEventListener mandatory in a JOGL-based application?

The callback approach of GLEventListener is sweet for a simple demo but seems restrictive when you try and scale to a ‘proper’ engine.

The current design already has a ‘viewport’ interface, the JOGL implementation of this interface contains a GLCanvas instance for each viewport on the frame. The engine manages the viewports, display, devices, etc. and invokes a set of ‘lifecycle’ methods on each viewport - start a new frame, clear the buffers, set the projection/modelview matrices, and so on.

The JOGL implementation has to delegate to canvas.display(), which then has to call back somehow to the engine if I want it to follow the same generic approach (which I do!), or replicate/emulate the lifecycle within the JOGL viewport. Neither of these approaches is particularly palatable.

So - do you HAVE to use GLEventListener? Or is there another approach?

For example, can I not request a GL object from the canvas, execute the lifecycle methods described above on it, then call some method to render the canvas, without having to go through the listener to get it?

  1. How to pass the global GL ‘context’ around.

The LWJGL methods are all static so I followed this approach in my engine design. There are APIs and implementation interfaces for texture management, transformations, shaders, etc. These then delegate to the actual OpenGL implementation.

For JOGL however I need to get the GL object from the current canvas. The only way to do this is set a nasty ‘global’ variable to the GLDrawable passed to the init() method of the listener, or fiddle my entire design to pass around this ‘context’ variable to EVERY method supported by the engine.

Again neither of these is particularly palatable.

Is there any way to get the ‘current’ GL variable?

  1. When is the GL ‘context’ valid?

The other thing that surprised me was the fact that one cannot invoke most (all?) of the GL methods without having a canvas already created.

My simplest demo has the proverbial rotating textured cube. When I first developed the JOGL implementation of the engine I got loads of null-pointer exceptions because the demo loaded and created the texture before the viewport. This constraint is documented in the JavaDoc, and I’ve seen several threads on this issue.

Firstly, is my assumption correct? (I think so because when I fiddled the engine to create a window straight away it worked fine).

Secondly, is there no way to get a GL object to do stuff like creating textures without having a viewport open?

Hope this all makes some sort of sense.

Cheers for any help.

  • chris

That sounds like an awful lot of work and potential bugs you could be introducing, just to switch to another library because it’s more “java like” (whatever that is). ???

Exactly my thoughts. The thing is, OpenGL is not a ‘java-like’ API to begin with so bending it into something that somehow resembles something OO won’t improve things IMHO.

Why do you want to go through all this trouble to move away from LWJGL to JOGL? Is there any problem you have with LWJGL? What do you hope to achieve by doing this?

LWJGL and JOGL are almost the same once you create a window, I don’t recommend switching to another if you already have done a significant amount of work with one.

If passing the gl context around to all of your methods that need it in your engine is that troublesome, it sounds like your engine isn’t very Java-like at this point (no offense intended, just an observation).

As for callbacks and such, this pdf chapter details two different JOGL frameworks, one callbacks, one active rendering, that might help you. I only use GLEventListener so I can’t really say otherwise.

http://fivedots.coe.psu.ac.th/~ad/jg2/ch15/index.html

Yes it will be a lot of work, and I’ll definitely introduce bugs ::slight_smile:

When I said Java-like I guess I meant the fact that it’s more integrated with the rest of the Java libraries (AWT mainly) than LWJGL is, rather than whether its OO (which it certainly isn’t!)

The real work is in the development of the engine which sits as an abstraction layer above the underlying OpenGL implementation (or at least that the idea). It’s the engine that contains the code to handle models, geometry, vector maths, texture blending, etc. The abstraction layer is basically just a wrapper for LWJGL or JOGL, so it really just a matter or cut-and-pasting the code and fiddling it to suit JOGL - indeed the method names are virtually identical. I just did a global search-and-replace, the basics of the JOGL implementation (creating a window, rendering a cube, texturing) only took me about an hour or so to get working :slight_smile:

Yes OpenGL is definitely not OO at all, but with a bit of patience and some (hopefully) good design one can come up with a system that hides the nasty non-OO aspects of the OpenGL interface - I think I’ve just about managed it with the LWJGL implementation.

I was just a little surprised to find that the GLEventListener almost forced my entire engine into a non-OO architecture.

I disagree with your first point. The OpenGL interfaces provided by either are obviously the same as they both support OpenGL v2.something or other. However the architecture of JOGL is VERY different from LWJGL: JOGL is integrated into the AWT/SWING paradigm, LWJGL is not (as far as I’m aware). For example, LWJGL uses the jinput.dll whereas JOGL (thankfully) uses the standard AWT KeyListener and so on.

He he none taken, I’m beginning to wonder about it myself :wink:

Looks like a really good tutorial, that should help me a lot - many thanks.

:wink: Maybe I should have taken more note of this paragraph at the start of that guide…

I predict you will rewoke the “thankfully” from this statement :wink:

Have you tried AWTGLCanvas and writing your own AWT KeyListener, MouseListener, etc.? I use LWJGL in Swing apps with no problem :slight_smile:

Having written the above I then did some more sniffing around and saw AWTGLCanvas which I’ve never come across before - Doh!

Cheers, I’ll check it out.

Yeah, check out AwtGLCanvas, it rocks. :slight_smile: You can share 99% of your code and have it run in either a Swing/AWT window or LWJGL’s native window with very little trouble (great for a level editor where you basically want the game running with a load of additional Swing controls around it). And unlike Jogl it doesn’t force you into a rigid application structure and lets you do it pretty much however you want to.

I’ve just realised I missed perhaps the most important point from my initial post - the rationale for wanting to use JOGL in the first place:

Basically I’ve got to the point where I’ve done most of the 3D code and was starting to focus on the 2D stuff (heads up display, text rendering, user interface, etc ) and was thinking that it would be sweet if I could mix the 3D canvas with the standard Java AWT/SWING interface.

I thought this wouldn’t be possible with LWJGL so I switched focus to JOGL - I was mistaken, the AWTGLCanvas looks great and I’m going to spend the afternoon getting to grips with it and integrate it into the LWJGL implementation of my engine.

So I’ll ask a slightly different question: What’s the best way of implementing a 2D HUD in JOGL (or LWJGL)? e.g. Is it viable to render a 3D scene using a JOGL canvas and overlay (for example) a transparent text widget over it? Or should/must the engine render the HUD using an orthogonal projection.

I’d prefer the former because then I’m reusing the standard Java AWT/SWING API and don’t have to reinvent the wheel to support 2D graphics, text rendering, buttons, progress bars, dialogs, etc.

If this is for an in-game HUD then personally I don’t think you should be using Swing for that as it’s completely unsuitable. Consider either writing some basic widgets yourself, or if you need a fully featured gui library then maybe something like Thinlet.

Alternatively the Xith3D guys had Swing widgets being rendered over a Jogl display. IIRC they were drawing the widgets to an offscreen image, copying that to a texture and drawing that with an ortho projection. That’s a bit more tricky as you’ll have to spoof the correct events (like mouse events) to your offscreen widgets but it can work equally well with Jogl or LWJGL.

If you’re just after an editor (ie. doesn’t have to look good) I’d just not overlay the controls and instead have them next to the GL display.

From the research I’ve done so far this seems to be the general consensus - there’s a few posts and tutorials around on mixing 2D/3D, which generally hint that one should be rendering a HUD using an orthogonal projection and custom widgets (or using the off-screen texture approach you suggested), but none of them say why?

It can work (just tried it), see this for example: http://weblogs.java.net/blog/campbell/archive/2006/10/easy_2d3d_mixin.html

So why not? Performance? The SWING multi-threading issue?

Well even with extensive look & feel customisation Swing still looks pretty ugly for use in a game, particularly when you’d like to have lots of animation going on. And as you say performance isn’t too hot and dealing with threading and events is more trouble than it’s worth IMHO.

The example uses Java2D OpenGL pipeline, which looks like a perfect solution for this, but in real world it has problems with OpenGL drivers’ bugs, unfortunatelly. It’s a big risk to use and depend on it in widely available application. Without the OpenGL pipeline, you have to copy from off-screen surface (pbuffer) to Swing JComponent, which has big performance hit, though it’s usable for small windows and/or interactive (non-realtime) 3D stuff.

This is a weird argument. It’s fully in your hands how components will look and feel, Swing is very flexible in this regard. I have working prototype of running Swing entirelly in OpenGL, without any copying from CPU->GPU and drawing directly with OpenGL in custom look and feel. And it’s very fast and smooth. But since there are some quirks needed to be resolved (as it currently works only in LWJGL’s native Display on Windows/Linux only), I’ve postponed any release until it’s generally usable. The concept of Swing is no fundamentally wrong, it’s just that it’s more linked to AWT than it should be.

If you need an example, I encourage you to look at my source code, in the class “main.GameGLView”, in the method “public final void display(GLAutoDrawable drawable)”, line 567. I use JOGL and it works fine :smiley:

OK guys, thanks again for the swift responses.

I’ve already got some HUD code integrated into my engine, at the moment it only supports rendering an orthogonal texture.

I think what I’ll do is add further classes for other widgets such as text, progress bars, etc. and use a smarty-pants strategy pattern to render whichever method turns out to be simplest/fastest/nicest.

I’m going to try the easiest approach first which is to simply overlay AWT/SWING transparent widgets over the 3D canvas and see how that works out.

If that doesn’t work, is too slow, or just too crap, then I can try the off-screen buffer approach, still using AWT/SWING.

And if that doesn’t work then I guess I’ll have to bite the bullet and implement the rendering myself ::slight_smile: using basic OpenGL drawing and stuff like texture fonts.

Afaik you won’t getting swing to work in a transparent overlay with LWJGL or JOGL GLCanvas. You can get it to work with JOGLs GLJPanel, which is usually slower than GLCanvas, because it needs copying of the framebuffer to the swing canvas unless the java 2d opengl pipeline is enabled. Unfortunately the opengl pipeline is not very robust atm…

Use a pure GL HUD.

Yep, just twigged that. It doesn’t work at all with the LWJGL canvas and I’ve already been told that GLJPanel + pipeline is iffy, oh well looks like the OpenGL HUD it is then.

Why is the least palatable option always the one you have to use ::slight_smile: