Skip to main content
Up and Coming
September 8, 2013

When there's no need to render twice

Conventional Rift engine design currently appears to focus on rendering the entire scene twice, once from each eye. The only alternative that seems to get discussed is stereo reprojection using a depth buffer, but that's universally agreed to be unsatisfactory.

But actually, there's no need to render your entire scene twice in every circumstance. Thanks to the Rift's display's low angular resolution, there's a fairly low distance threshold beyond which stereoscopic depth cues are no longer distinguishable. We can calculate this threshold distance thus:

  • Average interpupillary distance (IPD) ~= 0.064m

  • Best angular resolution = 1280px horizontal resolution / 90 degrees horizontal view angle = 14.22 pixels per degree

  • Smallest angular size of a pixel = 1 / 14.22 PPD = 0.07°

  • ∴ Distance at which stereoscopic effects are smaller than 1 pixel = 0.064 / tan(0.07°) ~= 52m


Additionally, as FredzL pointed out in IRC, distance stereopsis is not a primary depth cue at longer distances:


One technique to take advantage of stereo imagery being unnecessary beyond a given range would be a three-pass renderer:

  • Pass 1 renders the background from the centre camera with a near clipping plane of 60m, onto both eye render target textures

  • Pass 2 renders the left eye view from the left eye camera, with a far clipping plane of 60m, overlaid onto the left eye target texture

  • Pass 3 does the same for the right eye

  • Barrel distortion shader etc

The downside to this technique is that you're losing the benefit of the z-buffer cull, having to overdraw parts of your scene. However, this could be compensated in part by occlusion culling routines of other sorts - including portaling. For indoor scenes there would not be much benefit to this, however, as in most scenes that work well with portaling engines you've already got the vast majority of your rendered content in the foreground.

However, for scenes such as flight or space simulators (where your cockpit is the only thing within ~50m of you in normal gameplay, and therefore the only portion that needs to be rendered in stereo) this technique could make a huge difference to performance.

An alternative render order could be:
[list=2]
  • Passes 1 and 2 render left and right eye scenery with a far clipping plane of 60m, with the depth buffer rendered to an external render target for each eye

  • Pass 3 renders centre eye scenery with a near clipping plane of 60m, testing against a depth buffer written out from each eye in pass 1 and 2

  • Barrel distortion shader etc

  • I've not really thought much about this method yet, since it requires some way of substituting for having two independent z buffers. One way could be using the alpha buffer of the texture as a depth buffer for the depth test - but this would require some shader fiddling, and you lose transparency.

    What I'd like to know is - has anyone already tried to implement a similar technique, and if so, what did you discover? I find it hard to believe I could be the first person to try to implement such an obvious idea.

      11 replies

      SlowRiotAuthor
      Up and Coming
      July 2, 2014
      "JonathanVB" wrote:
      "SlowRiot" wrote:
      An alternative render order could be:
      [list=2]
    • Passes 1 and 2 render left and right eye scenery with a far clipping plane of 60m, with the depth buffer rendered to an external render target for each eye

    • Pass 3 renders centre eye scenery with a near clipping plane of 60m, testing against a depth buffer written out from each eye in pass 1 and 2

    • Barrel distortion shader etc

    • I've not really thought much about this method yet, since it requires some way of substituting for having two independent z buffers. One way could be using the alpha buffer of the texture as a depth buffer for the depth test - but this would require some shader fiddling, and you lose transparency.


      This could be done with a single depth buffer by taking the minimum depth between the left and right image (since the culling should be similar, and then just draw the left and right eye over the center eye scenery, since it is garunteed (not sure about shadows, effects, etc.) to be nearer to the center eye scenery.


      No, I don't think that would work. It would be possible to do what you describe by clearing the single depth buffer to 1 and just writing to the depth buffer only if the new value is less than the existing value; however, you wouldn't get accurate rendering in cases where an object is occluded in one eye's view and not another, for instance. There's no way I can see to get around having two separate depth buffers, but frame buffer objects in opengl do allow colour and depth buffer attachments so simply rendering to a separate FBO for each eye and then rendering the background with a combined depth buffer that's a result of the greatest depth (not least depth) for each fragment in each eye, and then blitting that new background into the depth 1 areas of the colour buffer of each eye would work. And then rendering each eye's FBO on a quad and doing your distortion and all the rest of it after that. But it's quite a complicated process and all the buffer shuffling might end up negating any speedup - it would depend on the scene.
      Oculus SDK on MinGW with Code::Blocks - http://code.voxelstorm.com/ovr_sdk_mingw_0.2.5c