22
\$\begingroup\$

In many common AAA titles (Source engine games especially), when the player reaches an area 'un-catered' for, such as out of bounds, or noclipping under the map; a strange effect occurs on the screen (buffer tearing?).

It can be described as being similar to the trail of windows that Windows XP may leave behind a window being dragged whilst theres a system hang.

I can only postulate that the developers do not clear the color buffer when refreshing the screen?

Is that correct? If so, why?

\$\endgroup\$
1
  • 8
    \$\begingroup\$ BTW, this is often called the "Hall of Mirrors" effect or HOM. \$\endgroup\$ Sep 25, 2011 at 23:25

2 Answers 2

36
\$\begingroup\$

Once upon a time, clearing the color and depth buffers actually took time. Doing a clear meant that the graphics card would have to walk every pixel of the framebuffer and write a value to it.

Because of this, game developers found that it would be more efficient to simply assume that, every frame, you would write to every pixel. They developed many techniques for taking advantage of this.

The color buffer is the easiest to ignore. Less easy is the depth buffer, because it would be polluted with old data. So what they did was simple.

On frame 0, they would render with a glDepthRange (or the D3D equivalent) of (0, 0.5), and they would use a glDepthFunc of GL_LESS (or GL_LEQUAL). This means that the farthest depth value you would ever get in the depth buffer is 0.5. So the largest value in the depth buffer at the end of frame 0 is 0.5 (assuming you wrote to every pixel).

On frame 1, they would change the depth range to (1, 0.5). Notice that in this case, the near depth value is larger than the far depth. But they would also change the depth func to GL_GREATER (or GL_GEQUAL), which reverses the meaning of the depth test. Because the largest value in the depth buffer at this point is 0.5, everything you write will have a value larger than this. Since the depth test was reversed, this effectively means that whatever was written on frame 0 is now farther away than everything that frame 1 will write. At the end of frame 1, the smallest value in the depth buffer is now 0.5.

And then they repeat.

On any hardware made since around 2003, this is no longer an optimization. Indeed, it is a negative optimization. Clearing the depth buffer actually makes hardware faster. No, really.

Basically, what happens is that clearing buffers doesn't actually write anything. They store some bits in the GPU's caches that let the system know what are the color/depth values they have been cleared to. When the system tries to write to a cache line of the framebuffer, it doesn't bother to read what's there, because it already knows that it is a blank field of the clear color/depth value. If you try to blend with what's there or do a depth test, again, no need to read: it knows what value to blend/test with/against.

So every first read/modify/write that you do on each cache line after a clear is just a write. It's free.

Plus, having a jagged depth buffer can work against Hyper-Z/Hierarchial-Z/any Z-culling optimizations in hardware. Yes, your scene will work against those eventually as you add detail. But if your depth buffer is jagged from previous renderings, even if those background objects are in the background, it can affect the efficiency of Z-culling techniques. And that's not going to help performance.

So you should never do this depth reversal technique in modern games.

Note: Jari makes a good point on tile-based rendering architectures (as found in most mobile platforms). Not clearing the depth can make things unpleasant there too.

\$\endgroup\$
3
  • \$\begingroup\$ Is your last statement implying to never do the depth buffer alternating or? Great answer. \$\endgroup\$ Sep 26, 2011 at 4:11
  • 1
    \$\begingroup\$ @Daniel Yes. I clarified my post. \$\endgroup\$ Sep 26, 2011 at 4:18
  • 3
    \$\begingroup\$ Additionally skipping the clear on binning architectures (like most OpenGL ES chips) causes massive performance loss, as the graphics chip can't make assumptions on the color buffer state. \$\endgroup\$ Sep 26, 2011 at 9:01
6
\$\begingroup\$

Yes, you're right that the back buffer isn't being cleared.

Why is because (mostly) that it's faster to use a custom shader that ping-pongs depth values in opposite directions each frame and rely on the fact that your game always renders every pixel on the screen.

So for zero cost you save one buffer clear per frame.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ I don't know about depth ping-ponging; every engine I'm familiar with clears the depth/stencil buffer each frame. But aside from that, yes, if the game renders all the pixels (as it should), you don't need to clear the color buffer. \$\endgroup\$ Sep 25, 2011 at 23:26
  • 1
    \$\begingroup\$ Could you give an example for the shader, good answer otherwise. \$\endgroup\$ Sep 26, 2011 at 0:41
  • 1
    \$\begingroup\$ I realize that you're asking about recent engines, reading @NathanReed's comment is how many PC-only engines work now. The Z buffer twist is an older technique, I'll see if I can find a reference. Console engines will mostly clear all the color buffer too, even one pixel showing the HOM effect Nathan named will fail a title and force it to go through submissions all over again. \$\endgroup\$ Sep 26, 2011 at 2:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .