Stretching the stencil buffer

What is the fastest way to draw to the stencil buf at, say 1/4 res. and then scale it up to the full image.

I’m doing this in order to speed up my shadow volumes (carmacks reverse).

Any other tips welcome!

cheers,
Nich

Hullo,

I believe you can accomplish what you’re looking for by setting the viewport (and projection matrix) to render a 1/4 sized image to the lower-left corner of the screen,
using glPixelZoom(2,2) and glCopyPixels.

HOWEVER… If you’re getting a speed-up by using a lower-resolution screen, then you are fill limited. If you are fill limited, reading/scaling/writing the stencil buffer will probably not improve your performance - the ‘writing’ at the end still has to write out a value for each pixel. Additionally, the ‘read’ /may/ consume fill-rate.

If your performance bottleneck is in geometry processing, then you /might/ benefit from re-using stencil buffer for a frame or two - if the delta between two frames is small enough it won’t be very noticeable. So long as shadows are the only thing you use stencil for, then you don’t need to save/restore the buffer.

That might also help with a CPU-bound, or fillrate limited application. The cost is visual quality. Humans are good at noticing things that aren’t quite right, though. It may not be an acceptable trade-off.

Hope you’ve enjoyed my ramblings…
– Jeff

Thaellin,

If you are fill rate limited because of massive stencil overdraw, rendering to quarter size and scaling at the end is still a win.

Originally posted by jwatte:

If you are fill rate limited because of massive stencil overdraw, rendering to quarter size and scaling at the end is still a win.

Right, this will likely depend on the overdraw involved. The blit method guarantees an overhead of 1x overdraw. Now, in the 1/4 case, if you only have a 2x average overdraw, this will be a win. ( 1 + 2 * .25 = 1.5 vs. 2) The important thing to remember is to analyze how much overdraw you have, rather than assuming this will just help.

One way to do this would be to use CopyPixels and PixelZoom. You set PixelZoom to double the image in each dimension. I am not so certain as to how well this will work on consumer cards. Stuff like copying pixels where the source and destination overlap may cause them to fall out of their best paths.

To elaborate:

I’ve been thinking a bit more about my approach.

I’m drawing stencilled shadows. What I want to do is to make the stencil shadows at 1/4 res, using the extra bandwidth to do many smaples/light. (for softened shadows)
Then, I would draw the light amount to the alpha buffer, adding for each pass, thus giving me an alpha buffer with light coverage at 1/4 res.

This I would scale to the full screen, and rerender the geometry at full res, using dest. alpha.

In pseudocode, it goes like this:

Render ambient lighted scene at 1&4 res
foreach light {
Calculate shadow volume
draw shadow volume to alpha
jitter light
draw shadow volume.
rescale alpha to fit entire screen
draw lighted geometry at full res.
}

I’ve just noticed, this removes the possibility of doing multiple lights. I could circumvent this by rendering the shadows to a texture, but then I would have to use a texture unit to mask the lights.

Does anyone have a suggestion for a better approach?

nich

jwatte: You’re right, of course. Bad miss on my part. Must need more coffee.

Have fun,
– Jeff