28

For a game in webgl where fps performance is important, what is the most efficient way to make a 2D HUD? I can think of 3 options, but its unclear to me what is the performance cost of each and which would be recommended as most efficient.

So what is the relative performance cost between the 3 following options:

A: render the hud with polygons in 3D using an orthographic camera and blend over the original scene. Advantage is advanced opengl effects are possible, at cost of manual arangement of containers.

B: build the HUD in html/css and let the browser do compositing. Inthis case is there a big perf hit with browser composition?

C: draw on a 2D canvas over the 3D canvas and let browser do compositing. Is this even possible and would I have issues with event propagation between canvases such as mouse events and focus.

Many thanks!

JayDee
  • 899
  • 1
  • 11
  • 19

2 Answers2

40

Option A is probably technically the fastest, but will bring with it a whole slew of other issues that you will need to handle manually. If you are updating text (health, ammo, etc) you'll have to come up with a text rendering routine, and those are non-trivial to say the least. If you interacting with the UI via a mouse or keyboard you'll need to handle that yourself, and the chances of you doing that robustly and efficiently enough to actually yield a better experience than the native browser widgets is slim. Point being, it's a lot of work for the potential to be a little faster.

Option B is, in my opinion, the way to go. The browser is quite good at compositing and even though there will be a perf hit because of it unless you are doing a really crazy detailed HUD I would guess that the hit will be negligible compared to other parts of your app (like JS logic). Plus this is a route that should "magically" get better as time goes on and Browsers become more efficient at what they do. IMO the biggest downside here is that you may encounter some rendering bugs if you're using some of the latest and greatest CSS effects to style your HUD the way you want it, but again that should go away as time goes on.

Option C is, to my knowledge, not possible within a single canvas. You could have a separate 2D canvas layered over your 3D one and draw your HUD to it, but at that point you're inheriting all of the problems of A and B with none of the benefits. I can see no good reason to recommend it.

I think one of the big advantages WebGL has over many native 3D platforms is that it has trivial access to one of the most widely used and most flexible UI frameworks on the planet (HTML). Ignoring that advantage is going to be a colossal effort with very little tangible benefit. Use the tools that are available to you, and don't concern yourself too much over lost milliseconds because of it. I promise you that there are much larger issues that you'll be facing while working on your game and your time and effort would be far better spent there than trying to reinvent this particular wheel.

Toji
  • 31,923
  • 20
  • 95
  • 113
  • 1
    Note that, if you go with Option C (2D canvas overlaid on top of your 3D canvas), you'll take a pretty big performance hit on iOS 8. This approach halved my framerate! – lazd Aug 27 '14 at 19:44
0

While I agree that Option B is preferred in most situations, Option C is possible and may be needed for HUDs in WebVR (unless you want to render the DOM to a texture using something like DOM2AFrame).

I found this blog on how to implement Option C using Three.js. It creates a separate scene for the HUD on top of the original scene and uses a 2D canvas to generate the HUD texture. Here is a Codepen link with an example, see lines 57-78, starting with:

var hudCanvas = document.createElement('canvas')
hudCanvas.width = width
hudCanvas.height = height
var hudBitmap = hudCanvas.getContext('2d')

Aframe also has pre-built UI components that could be used, see ex. 1, ex. 2

sjcobb
  • 1