Glossy Screen Space Reflections

Started by
10 comments, last by jameszhao00 11 years, 12 months ago
Glossy Screen Space Reflections

For my Game Architecture final project (@RPI), I worked on a glossy screen space reflection (SSR) tech demo. Implementation details...

Video (best in 720P)

[media]
[/media]
Advertisement
Very interesting. I couldn't see the timmings on the video but isn't this a performance killer? From what I understand, for each pixel you're casting a good deal of rays and ray casting them in screen space will require lots of sampling from the G-Buffer.

You should also use a more interesting test scene, with more complexity and lighting, to show the eye candy.

Anyway, great work! I'm curious to know more so don't hesitate to write a more detailed article on your blog about your implementation.
Indeed this looks very interesting, but I'd also be interested in some performance specs

I've been looking into SSR for use in a game I'm working on, but the I always considered the performance hit too great to actually apply it
Would be nice to see how your technique performs :)

I gets all your texture budgets!

Perhaps dynamically creating a quad-tree over the depth buffer could speed up the whole process.

Very interesting. I couldn't see the timmings on the video but isn't this a performance killer? From what I understand, for each pixel you're casting a good deal of rays and ray casting them in screen space will require lots of sampling from the G-Buffer.

You should also use a more interesting test scene, with more complexity and lighting, to show the eye candy.

Anyway, great work! I'm curious to know more so don't hesitate to write a more detailed article on your blog about your implementation.


Thanks!

I only trace one ray per pixel. The intermediate result is extremely noisy, but you gotta live with that. The bilateral-ish blur pass smooths everything out.

Here're some pictures


ssr_pass0.png

ssr_pass1.png
I used this simple scene as SSR is quite... bad for anything complex. In the Crysis SSR videos I've seen, the reflection only contained cylindrical cans/bottles/tubes. I imagine if you're using glossy SSR in a real game, it would have to have to be for relatively rough surfaces where reflections fade out quickly with respect to reflection distance. This let's us constrain the SSR rendering to areas where we're likely to have information.


Indeed this looks very interesting, but I'd also be interested in some performance specs

I've been looking into SSR for use in a game I'm working on, but the I always considered the performance hit too great to actually apply it
Would be nice to see how your technique performs smile.png

My unoptimized, debug shader (the video) running at 1080p with no MSAA takes roughly 20 ms, evenly divided between the 2 passes (SSR and Blur). (for reflections on 3/4 of the screen). The bilateral-ish blur is a 9 tap rotated poisson disc, where I dynamically compute a gaussian weight for each tap (so probably the 2nd pass is way cheaper once you optimize it). For more details look on the blog biggrin.png

I cap myself at 30 samples per ray trace. I currently dynamically adjust the step size based on dist(actual z, desired z). You will probably also want to start out with a small step size (as the artifacts near the surface are the most visible) and increase it (to a cap). Also, you can probably get away with larger step sizes (thus more error) as the surface roughness increases.


Perhaps dynamically creating a quad-tree over the depth buffer could speed up the whole process.


Yes you can definitely do min-max (more so the min) depth mip maps for this. I decided that glossy ssr wasn't worth pursuing so didn't implement it. Instead I'm now working on a hybrid path tracer/rasterizer techdemo biggrin.png

I only trace one ray per pixel. The intermediate result is extremely noisy, but you gotta live with that. The bilateral-ish blur pass smooths everything out.


Only one sample? Impressive. I still think you could improve the blur to mask out the noise even further. Forget the poisson disc blur, not only it gives you a noisy result but the somewhat random texture sampling must be harming your performance. You should instead try applying a gaussian blur or even two passes of gaussian blur .


I used this simple scene as SSR is quite... bad for anything complex. In the Crysis SSR videos I've seen, the reflection only contained cylindrical cans/bottles/tubes. I imagine if you're using glossy SSR in a real game, it would have to have to be for relatively rough surfaces where reflections fade out quickly with respect to reflection distance. This let's us constrain the SSR rendering to areas where we're likely to have information.


I have to disagree with you on that, SSR will shine on more detailed scenes because all the visual complexity will help hiding the fact that only the visible portions of the scene get reflected. The fresnel term will also help with this by forcing the reflection to show only at grazing angles. You should really try it out with a better scene.

Only one sample? Impressive. I still think you could improve the blur to mask out the noise even further. Forget the poisson disc blur, not only it gives you a noisy result but the somewhat random texture sampling must be harming your performance. You should instead try applying a gaussian blur or even two passes of gaussian blur .


Full gaussian blurs are very expensive in this case, as the blur is bilateral-ish and not separable (maybe you can still do it in a separable fashion... but I don't know how that would look). Temporal supersampling the reflection jittering might be a good choice though (for when nothing moves. you can't really temporally reproject reflections for motion).


I have to disagree with you on that, SSR will shine on more detailed scenes because all the visual complexity will help hiding the fact that only the visible portions of the scene get reflected. The fresnel term will also help with this by forcing the reflection to show only at grazing angles. You should really try it out with a better scene.



Whether the quality is acceptable depends on the specific usage. If you have a fbx scene file that you want me to try out, please send it to me and I'll try it out smile.png
Full gaussian blurs are very expensive in this case, as the blur is bilateral-ish and not separable (maybe you can still do it in a separable fashion... but I don't know how that would look).
When doing SS shadow/occlusion rays, I have used a separated horizontal/vertical bilateral-ish Gaussian blur (even though it's actually not a separable filter!).
For SSAO, at half-resolution, we took 4 samples per pixel (kind-of 4 "rays", but without stepping/refinement - only 1 sample), which produced an extremely noisy result. We then bilateral blurred horizontally with gaussian-ish weights, then vertically (optionally in a loop if you really want to kill the noise), and then we bilaterally upsampled back to full resolution.
Technically, it's really not correct (you get different results whether you do the H pass or the V pass first), but the blur worked like a charm anyway.

As an aside that might be helpful for optimising your blur -- we only required our SSAO/SSDO effect to be applied to players in our world (and not the world itself), which allowed for skipping a lot of work -- if most of your scene is non-glossy, you might be able to do the same, and then use a more expensive blur.
Our solution was to use the alpha channel to mask out these "self-shadow receivers" and then down-sampled that mask to be ~1/32[sup]th[/sup] resolution. This low-res mask is then used by a tile-classification scheme, where you break the screen up into small tiles of pixels -- e.g. at 1024*768, i can have a 32*24 mask where every mask-texel corresponds to a 32*32 area in the original resolution. When applying the blur passes, instead of using a full-screen quad, we use a grid of quads (e.g. where each grid-square covers 32*32 pixels) and each quad samples the appropriate mask-texel to determine whether that quad is useful or not. If a quad isn't useful, it multiplies it's position by 0 to skip processing of any pixels in that tile.

Full gaussian blurs are very expensive in this case, as the blur is bilateral-ish and not separable (maybe you can still do it in a separable fashion... but I don't know how that would look).


Actually, full gaussian blurs are more than appropriate for these cases. It's true they are not fully separable, but in practice they do an excelent job at removing the noise and the visual artifacts from not being separable are generally unnoticeable. Moreover, their performance is pretty good since they do coherent reads from the textures. In fact, they are already used by some people to remove the fine grained noise from effects like soft shadowmapping with randomized sampling.

I have to disagree with you on that, SSR will shine on more detailed scenes because all the visual complexity will help hiding the fact that only the visible portions of the scene get reflected. The fresnel term will also help with this by forcing the reflection to show only at grazing angles. You should really try it out with a better scene.


More complexity just guarantees that you have more places where a screen-space algorithm will fall completely flat on its face, due to the fact that the information that you need just isn't there. The algorithm is really at its worst when you have lots of complexity causing occlusion of the surfaces you need to sample...the scene that the OP demonstrated is probably the best case scenario in that regard.

This topic is closed to new replies.

Advertisement