bevy
bevy copied to clipboard
Screen Space Ambient Occlusion (SSAO)
Objective
- Add Screen space ambient occlusion (SSAO). SSAO approximates small-scale, local occlusion of indirect diffuse light between objects. SSAO does not apply to direct lighting, such as point or directional lights.
- This darkens creases, e.g. on staircases, and gives nice contact shadows where objects meet, giving entities a more "grounded" feel.
- Closes https://github.com/bevyengine/bevy/issues/3632.
Solution
- Implement the GTAO algorithm.
- https://www.activision.com/cdn/research/Practical_Real_Time_Strategies_for_Accurate_Indirect_Occlusion_NEW%20VERSION_COLOR.pdf
- https://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
- Source code heavily based on Intel's XeGTAO.
- Add an SSAO bevy example.
Algorithm Overview
- Run a depth and normal prepass
- Create downscaled mips of the depth texture (preprocess_depths pass)
- GTAO pass - for each pixel, take several random samples from the depth+normal buffers, reconstruct world position, raytrace in screen space to estimate occlusion. Rather then doing completely random samples on a hemisphere, you choose random slices of the hemisphere, and then can analytically compute the full occlusion of that slice. Also compute edges based on depth differences here.
- Spatial denoise pass - bilateral blur, using edge detection to not blur over edges. This is the final SSAO result.
- Main pass - if SSAO exists, sample the SSAO texture, and set occlusion to be the minimum of ssao/material occlusion. This then feeds into the rest of the PBR shader as normal.
Blockers
- MSAA support for SSAO.
- https://github.com/bevyengine/bevy/pull/7356
- https://github.com/bevyengine/bevy/pull/7291 (increases SSAO quality)
- https://github.com/bevyengine/bevy/pull/7051 (fixes how occlusion is used, not a direct dependency)
Future Work
- Faster coordinate space conversions (don't do full matrix multiples, preconvert depth/normals)
- Big performance boost!
- SSAO spatial denoise 2 pixels per thread, instead of 1 (XeGTAO says this is faster, need to benchmark)
- Validate all heuristics and constants vs reference renders (XeGTAO has a mode for this)
- F16 math
- Bent normals
- GTSO
Changelog
- Added ScreenSpaceAmbientOcclusionSettings and ScreenSpaceAmbientOcclusionBundle
That looks superb, really looking forward to try this! :)
There's a few changes to examples that are not documented in the PR description. Also this is a 50+ file change, the PR description could be a tiny bit more detailed on what's going on, like explaining roughly how the implementation works and/or is integrated in Bevy, to help reviewers and future users.
Note that this PR directly builds on the TAA PR, as SSAO will render differently when TAA is present, for increased quality. Similarly, this PR requires wgpu 0.15, and builds on the PR adding support for it. Most of the files changed are due to those PRs, and until they're merged I'm going to keep this PR as a draft. It's not really intended to be reviewed yet, although I'm glad people are excited for it :). If anyone does want to review it, look at the crates/bevy_pbr/src/ssao
folder. Everything else is just miscellaneous changes.
I can't really explain the whole algorithm, it's best to read the linked GTAO paper and presentation, and XeGTAO's readme for a better idea of how it works. I will add a small summary, however.
There's still a bunch of perf improvements I can make, and some other tweaks like a better denoiser, and implementing bent normals. But I'm marking this as not a draft anymore, as it's fine as it is, and I'd like feedback on what I have so far.
The shadow seems too dark compared with the preview image. And there is a gray bar on the top of the left cube.
Guessed window scale factor: 1
AdapterInfo { name: "NVIDIA GeForce GTX 1650", vendor: 4318, device: 8089, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "530.41.03", backend: Vulkan }
SystemInfo { os: "Linux 22.1.0 Manjaro Linux", kernel: "5.15.108-1-MANJARO",
Yes, I was working on additional changes and ended up breaking things. Go back to commit 3cc7389e13521155d33751bab5d83ca2276d4fa2 for the working code.
I've reverted all of my WIP things that broke SSAO. Lets ship the MVP I have now, and later we can improve on it. I currently lack time and motivation to perfect this.
I cancelled the merge because I just noticed that the ScreenSpaceAmbientOcclusionPlugin
is added by default, which means we're spamming the console with this error by default:
ERROR bevy_pbr::ssao: SSAO is being used which requires Msaa::Off, but Msaa is currently set to Res(Sample4)
We'll need to resolve that first.