Skip to content

Conversation

@JMS55
Copy link
Contributor

@JMS55 JMS55 commented Jan 28, 2023

image

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 Screen Space Ambient Occlusion #3632.

Solution

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.

Future Improvements

  • Maybe remove the low quality preset for now (too noisy)
  • WebGPU fallback (see below)
  • Faster depth->world position (see reverted code)
  • Bent normals
  • Try interleaved gradient noise or spatiotemporal blue noise
  • Replace the spatial denoiser with a combined spatial+temporal denoiser
  • Render at half resolution and use a bilateral upsample
  • Better multibounce approximation (https://drive.google.com/file/d/1SyagcEVplIm2KkRD3WQYSO9O0Iyi1hfy/view)

Far-Future Performance Improvements

Other Interesting Papers

Platform Support


Changelog

  • Added ScreenSpaceAmbientOcclusionSettings, ScreenSpaceAmbientOcclusionQualityLevel, and ScreenSpaceAmbientOcclusionBundle

Copy link
Member

@cart cart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic work! I did a rough "port pass" over the shader code and things seem to line up well.

@JMS55 JMS55 added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Jun 18, 2023
Copy link
Member

@cart cart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

@cart cart enabled auto-merge June 18, 2023 19:09
@cart cart disabled auto-merge June 18, 2023 19:17
@cart
Copy link
Member

cart commented Jun 18, 2023

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.

@cart cart enabled auto-merge June 18, 2023 20:53
@cart cart added this pull request to the merge queue Jun 18, 2023
Merged via the queue into bevyengine:main with commit af9c945 Jun 18, 2023
@JMS55 JMS55 mentioned this pull request Jun 18, 2023
13 tasks
NoahShomette pushed a commit to NoahShomette/bevy that referenced this pull request Jun 19, 2023
![image](https://github.com/bevyengine/bevy/assets/47158642/dbb62645-f639-4f2b-b84b-26fd915c186d)

# 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 bevyengine#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](https://github.com/GameTechDev/XeGTAO/blob/0d177ce06bfa642f64d8af4de1197ad1bcb862d4/Source/Rendering/Shaders/XeGTAO.hlsli).
- 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.

---

## Future Improvements
- Maybe remove the low quality preset for now (too noisy)
- WebGPU fallback (see below)
- Faster depth->world position (see reverted code)
- Bent normals 
- Try interleaved gradient noise or spatiotemporal blue noise
- Replace the spatial denoiser with a combined spatial+temporal denoiser
- Render at half resolution and use a bilateral upsample
- Better multibounce approximation
(https://drive.google.com/file/d/1SyagcEVplIm2KkRD3WQYSO9O0Iyi1hfy/view)

## Far-Future Performance Improvements
- F16 math (missing naga-wgsl support
https://github.com/gfx-rs/naga/issues/1884)
- Faster coordinate space conversion for normals
- Faster depth mipchain creation
(https://github.com/GPUOpen-Effects/FidelityFX-SPD) (wgpu/naga does not
currently support subgroup ops)
- Deinterleaved SSAO for better cache efficiency
(https://developer.nvidia.com/sites/default/files/akamai/gameworks/samples/DeinterleavedTexturing.pdf)

## Other Interesting Papers
- Visibility bitmask
(https://link.springer.com/article/10.1007/s00371-022-02703-y,
https://cdrinmatane.github.io/posts/cgspotlight-slides/)
- Screen space diffuse lighting
(https://github.com/Patapom/GodComplex/blob/master/Tests/TestHBIL/2018%20Mayaux%20-%20Horizon-Based%20Indirect%20Lighting%20(HBIL).pdf)

## Platform Support
* SSAO currently does not work on DirectX12 due to issues with wgpu and
naga:
  * gfx-rs/wgpu#3798
  * gfx-rs/naga#2353
* SSAO currently does not work on WebGPU because r16float is not a valid
storage texture format
https://gpuweb.github.io/gpuweb/wgsl/#storage-texel-formats. We can fix
this with a fallback to r32float.

---

## Changelog

- Added ScreenSpaceAmbientOcclusionSettings,
ScreenSpaceAmbientOcclusionQualityLevel, and
ScreenSpaceAmbientOcclusionBundle

---------

Co-authored-by: IceSentry <[email protected]>
Co-authored-by: IceSentry <[email protected]>
Co-authored-by: Daniel Chia <[email protected]>
Co-authored-by: Elabajaba <[email protected]>
Co-authored-by: Robert Swain <[email protected]>
Co-authored-by: robtfm <[email protected]>
Co-authored-by: Brandon Dyer <[email protected]>
Co-authored-by: Edgar Geier <[email protected]>
Co-authored-by: Nicola Papale <[email protected]>
Co-authored-by: Carter Anderson <[email protected]>
james7132 pushed a commit to james7132/bevy that referenced this pull request Jun 19, 2023
![image](https://github.com/bevyengine/bevy/assets/47158642/dbb62645-f639-4f2b-b84b-26fd915c186d)

# 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 bevyengine#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](https://github.com/GameTechDev/XeGTAO/blob/0d177ce06bfa642f64d8af4de1197ad1bcb862d4/Source/Rendering/Shaders/XeGTAO.hlsli).
- 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.

---

## Future Improvements
- Maybe remove the low quality preset for now (too noisy)
- WebGPU fallback (see below)
- Faster depth->world position (see reverted code)
- Bent normals 
- Try interleaved gradient noise or spatiotemporal blue noise
- Replace the spatial denoiser with a combined spatial+temporal denoiser
- Render at half resolution and use a bilateral upsample
- Better multibounce approximation
(https://drive.google.com/file/d/1SyagcEVplIm2KkRD3WQYSO9O0Iyi1hfy/view)

## Far-Future Performance Improvements
- F16 math (missing naga-wgsl support
https://github.com/gfx-rs/naga/issues/1884)
- Faster coordinate space conversion for normals
- Faster depth mipchain creation
(https://github.com/GPUOpen-Effects/FidelityFX-SPD) (wgpu/naga does not
currently support subgroup ops)
- Deinterleaved SSAO for better cache efficiency
(https://developer.nvidia.com/sites/default/files/akamai/gameworks/samples/DeinterleavedTexturing.pdf)

## Other Interesting Papers
- Visibility bitmask
(https://link.springer.com/article/10.1007/s00371-022-02703-y,
https://cdrinmatane.github.io/posts/cgspotlight-slides/)
- Screen space diffuse lighting
(https://github.com/Patapom/GodComplex/blob/master/Tests/TestHBIL/2018%20Mayaux%20-%20Horizon-Based%20Indirect%20Lighting%20(HBIL).pdf)

## Platform Support
* SSAO currently does not work on DirectX12 due to issues with wgpu and
naga:
  * gfx-rs/wgpu#3798
  * gfx-rs/naga#2353
* SSAO currently does not work on WebGPU because r16float is not a valid
storage texture format
https://gpuweb.github.io/gpuweb/wgsl/#storage-texel-formats. We can fix
this with a fallback to r32float.

---

## Changelog

- Added ScreenSpaceAmbientOcclusionSettings,
ScreenSpaceAmbientOcclusionQualityLevel, and
ScreenSpaceAmbientOcclusionBundle

---------

Co-authored-by: IceSentry <[email protected]>
Co-authored-by: IceSentry <[email protected]>
Co-authored-by: Daniel Chia <[email protected]>
Co-authored-by: Elabajaba <[email protected]>
Co-authored-by: Robert Swain <[email protected]>
Co-authored-by: robtfm <[email protected]>
Co-authored-by: Brandon Dyer <[email protected]>
Co-authored-by: Edgar Geier <[email protected]>
Co-authored-by: Nicola Papale <[email protected]>
Co-authored-by: Carter Anderson <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Oct 29, 2025
# Objective

This PR is to add SSAO support on WebGPU.

## Solution
Add r16float detect and fallback to r32float if not supported. FYI the
initial ssao PR [here](#7402).

## Testing

- Did you test these changes? If so, how?
     Yes, here is the command to test the ssao example 
`RUSTFLAGS="--cfg getrandom_backend=\"wasm_js\"" cargo run --example
ssao --target wasm32-unknown-unknown --features webgpu`
and then http://localhost:1334, make sure it supports
[WebGPU](https://caniuse.com/webgpu)

- Are there any parts that need more testing?
 N/A
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
1. For the R32Float fallback, only the 1st commit is needed. However, I
ran into some strange flickering issue on Chrome (and Chrome canary
too), so I added a "detect_r16float_support" flag and a temp fix in the
2nd and 3rd commit, which are intended to be reverted when merging.
2. with the 1st commit, Safari works fine, but Chrome has the
flickering, and I fixed it by partially reverting a shader change from
#20313, which is very strange. It
is probably caused by some shader optimization issue in Chrome, and I
have no clue why, as the change is just moving the calculation to a
different function.
Here is the flickering on Mac Chrome(140.0.7339.133 (Official Build)
(arm64))
<img width="353" height="327" alt="chrome_ssao"
src="https://github.com/user-attachments/assets/0666673f-508e-4b57-a152-19327ffdb6f3"
/>


- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Tested on native(mac) and WebGPU. To test on native, set
"detect_r16float_support" to false to force R32Float.
I couldn't make the WebGPU ssao example running on Windows 11 Chrome or
Firefox, there is some error in 'taa_pipeline' .
 
---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Screen Space Ambient Occlusion

9 participants