Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Screen Space Ambient Occlusion #3632

Closed
superdump opened this issue Jan 10, 2022 · 0 comments · Fixed by #7402
Closed

Screen Space Ambient Occlusion #3632

superdump opened this issue Jan 10, 2022 · 0 comments · Fixed by #7402
Assignees
Labels
A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible

Comments

@superdump
Copy link
Contributor

superdump commented Jan 10, 2022

Description

  • If you hold your hand up with your fingers together, out of the line of sight of any direct lighting, you will notice that where your fingers meet each other gets gradually darker. This can also be noticed in edges/corners of rooms where walls meet. This is called ambient occlusion.
  • I think of ambient light as light that has bounced around many times of many surfaces and so it comes from all directions. But, if some directions in the hemisphere tangent to a surface are blocked, then ambient light cannot reach the surface at that point from those directions and so that point on the surface is dark than one where the hemisphere is unimpeded.
  • This subtle shadowing of ambient light adds significant visual depth and enhances geometric detail which can otherwise look quite flat

Solution

  • There are many approaches to calculating ambient occlusion. Occlusion of a model's surfaces by itself can be baked into occlusion textures. Occlusion between different objects in the scene, for example a cupboard against a wall, can be done in real-time as part of the real-time rendering effects.
  • A simple approach called Screen Space Ambient Occlusion involves running a prepass to populate the depth buffer as well as to calculate normals and write them into a texture. A second pass is run which, for each fragment calculates the world position of the fragment from the fragment uv and the depth and projects back to world space. More samples are taken from the depth buffer from within a hemisphere oriented along the surface normal. The percentage of samples that have depth buffer values closer to the camera gives an approximation of the percentage of directions that are occluded.
  • The current state of the art technique is called Ground-Truth Ambient Occlusion (GTAO) and is a drop-in replacement for SSAO but is a significantly more complicated horizon-based technique that builds on Horizon-Based Ambient Occlusion and enhanced versions thereof.
  • https://github.com/superdump/bevy/tree/ssao-pipelined
    • A partial implementation of SSAO including the depth/normal prepass, and SSAO pass using a low discrepancy sequence hemispherical sampling kernel in tangent space (wow, that's a mouthful - just imagine a unit hemisphere pointing along +z), and randomly rotating that sampling kernel using blue noise, but no blur, plus bugs

Next Steps

  • Rebase, fix bugs, implement blur, make PR
@superdump superdump changed the title Screen Space Ambient Occlusion - https://github.com/superdump/bevy/tree/ssao-pipelined Screen Space Ambient Occlusion Jan 10, 2022
@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible labels Jan 10, 2022
@superdump superdump self-assigned this Jan 16, 2022
@cart cart closed this as completed in af9c945 Jun 18, 2023
NoahShomette pushed a commit to NoahShomette/bevy that referenced this issue 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 issue 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]>
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
Projects
Status: Done
2 participants