2D Rendering

I’m trying to figure out the best way to incorporate a 2D HUD into my OpenGL application.

I’ve considered using a JPanel and drawing my 2D the Swing way, but I found some drawbacks
-The current JPanel is really slow. While one of my demos flies at 900 FPS with a GLCanvas, a JPanel sinks it to 50 FPS (and even then, I suspect it’s lower becasue the animation is choppy)
-While JPanel is much faster in Mustang, Mustang’s still more than eight months from release.

  • Even in Mustang, the Vertex Buffer Object is really slow. The demo also has problems, with windows sometimes vanishing or terminating abruptly.

My next best idea so far is to create a large texture on the GPU, draw my HUD into a BufferedImage and use glTexSubimage2D() to upload it whenever my HUD changes.

Or would it be best to keep my image on the client side and use glDrawPixels() to draw my image each pass?

I will potentially have a 1600x1200 screen size, and would appreciate hearing what worked for other folks with HUD creation.

I’ve come across the same choice lately. It appeared that (as always) there is no definitive answer to this.

  • Using Swing is a quick but a bit ineffective way of doing the job (for the moment). Perhaps Mustang will solve this (albeit only with the Sun JVM ?). I used the bridge existing in Xith3D it gives you a good example of how to do this (It is a bit buggy with the event processing).
  • Using a texture for the complete screen was not adapted for my system (too high video memory & fill rate consumption) but I can imagine that some UI would benefit for it (when they cover most of the screen). I did not try this.
  • Using a texture per top level widget seems to be a good trade-off since it allows you to only update the modified part of the texture and not send the whole widget like you would with glDrawPixel.
  • For some widgets it happens to be usefull to be allowed to provide free geometry (example : in the player selection buttons of my game, you have an animated model of the selected character).

In my system, I end up using the main engine scenegraph for the UI part ;

  • A top-level shell is in charge of managing the dispatch of events to top-level widgets as well as managing the laying-out updates,
  • By default, each widget adds up and manages the geometry it wants to the top-level shell,
  • Special top-level window allows for texture cached widgets (planned in the design but not yet implemented),
  • The z components of the geometry define the z-ordering of the widgets.
  • The UI is rendered in its own pass after clearing the depth buffer.
    This allows the UI to use all the feature of the graphic engine (like animated models, correctly sorted blending,…).

This design looked to me like a good compromise between the performance cost and the design flexibility.
I think that you can come with lots of clean other solution for this.

For another solution, you may want to have a look to http://www.cegui.org.uk/ which has proven to work for a few projects.

         Vincent

The most efficient way is ofcourse to ditch software rendering and use opengl instead. I admit it is not easy, and it limits what you can do. Still I think it is the way most real games does it.

I haven’t tried doing this before either, but I wonder whether you could draw your hud as opengl objects prior to drawing anything else. That way you can draw the without any transformations effecting them. Then you can do any other trick that you would expect of an OpenGL ‘object’. The thing which might cause a problem is the interaction with the lighting model. I’ll have to give it a go. As with the previous posters, I would be curious as to what a seasoned developer would suggest.

I will see if gamedev.net suggests anything.

I would suggest drawing your gui overlay after the rest of your scene. The sequence of operations might go something like:

  1. draw scene
  2. Set projection matrix to orthographic
  3. Clear depth buffer
  4. Disable lighting
  5. Draw GUI elements

As to prior transformations affecting your GUI, surely all that is needed is some pushMatrix()/popMatrix() activity?

However, I’m about as green an OpenGL developer as you’ll find, so this is probably all rubbish. :frowning: