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

Adding a screen space AO map parameter to materials #20419

Closed
Mcgode opened this issue Sep 25, 2020 · 1 comment
Closed

Adding a screen space AO map parameter to materials #20419

Mcgode opened this issue Sep 25, 2020 · 1 comment

Comments

@Mcgode
Copy link
Contributor

Mcgode commented Sep 25, 2020

Important note

Screen Space Ambient Occlusion (abbreviated to SSAO) is meant here as a general notion of a post processing algorithm obscuring pixels on screen. If I talk about the classic SSAO algorithm, I'll use the following syntax: SSAO

Is your feature request related to a problem? Please describe.

The SSAO approach used in three.js (like SSAOPass or SAOPass) is only suitable for applying on indirectly lit surfaces. Start using direct lights in the scene, and the render is incorrect, as the AO texture will thoughtlessly obscure lit and unlit surfaces alike. This is not the expected result. This is why SSAO is generally used in deferred shading, but from what I've been able to gather, deferred shading is a very complex feature and as such is not supported by three.js

Describe the solution you'd like

The idea is to use the SSAO computed texture directly as an AO map in the three.js pipeline, and a first approach is to use projected vertex coordinates on screen as uv2. This does not work (see below), so a new parameter is required.
The SSAO map would be passed to the material. It would look like something like this:

object.material = new THREE.MeshStandardMaterial()  
 
// Similarly to what we can do right now with an AO map...  
object.material.aoMap = aoTexture;  
object.material.needsUpdate = true;  
 
// .. we could have the same feature for that SSAO map  
object.material.ssaoMap = ssaoRenderTarget.texture;  
object.material.needsUpdate = true;  

To do that, we need to extend the material lib and the AO shaders a bit, and pass the current renderer/renderTarget size to the fragment shader, with that we'll be able to retrieve the AO from the SSAO map like this:

float ambientOcclusion = ( texture2D( ssaoMap, gl_FragCoord.xy / renderSize ).r - 1.0 ) * aoMapIntensity + 1.0;  

We'll then be able to use the ao value for the rest of the pipeline calculations without a problem, accounting for direct lights as expected.

I have already forked the library and made a dedicated branch: link

Changes required are small but occur in several files. However, it could be used for any per-pixel ambient occlusion algorithm. So I wonder what are your thought about this ?

Describe alternatives you've considered

I tried to project vertices positions on screen to get uv2 coordinates in screen space and pass the SSAO map in standard aoMap parameter. It has some interesting results, but shows big artefacts due to perspective projection and uv2 interpolation.

I made a dedicated repo for this approach : link

Additional context

Using an SSAO Pass (notice how the yellow areas are darkened instead of going back to orange) (demo):
image

Using my forked three.js, passing the ao map to the material (demo):
image

I work at Dioxygen Software, we are mainly making 3D configurators (www.dualbox.com), but also develop custom online 3D modelers and specialized viewers for businesses. All based on Three.js

@Mugen87
Copy link
Collaborator

Mugen87 commented Jan 25, 2024

A solution for this has been provided in #27475.

@Mugen87 Mugen87 closed this as completed Jan 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants