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

Distance-based Gaussian weighting for Ambient Occlusion #12316

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

jjhembd
Copy link
Contributor

@jjhembd jjhembd commented Nov 19, 2024

Description

Ambient Occlusion (AO) for geospatial data needs to produce good results at a wide range of scales, without requiring the user to adjust parameters for each zoom level. This PR redefines the weight function for AO as a normalized Gaussian window, with a variance that scales with the distance from the camera.

Before this PR, the AO effect disappears when zoomed out:
image

After this PR, the AO effect blurs wider, remaining visible (though lower intensity) when far from the camera:
image

Issue number and link

Fixes #10106.

Testing plan

Author checklist

  • I have submitted a Contributor License Agreement
  • I have added my name to CONTRIBUTORS.md
  • I have updated CHANGES.md with a short summary of my change
  • I have added or updated unit tests to ensure consistent code coverage
  • I have updated the inline documentation, and included code examples where relevant
  • I have performed a self-review of my code

#TODO

  • Rework uniforms to expose loop counts and Gaussian window size
  • Add fallback to support variable loop counts in WebGL1
  • Add fallback with deprecation message to support old uniforms
  • Test performance, pre-compute window weights if needed
  • Choose good defaults
  • Resolve artifact at frustum boundary
  • Remove blur method, possibly replace with bilateral filtering

@jjhembd jjhembd marked this pull request as draft November 19, 2024 17:57
Copy link

Thank you for the pull request, @jjhembd!

✅ We can confirm we have a CLA on file for you.

@ggetz
Copy link
Contributor

ggetz commented Nov 20, 2024

Thanks @jjhembd! Excited to get this in!

Is the code ready for review yet, or should we wait for the uniform changes to go in first?

@jjhembd
Copy link
Contributor Author

jjhembd commented Nov 21, 2024

The code is now ready for performance testing with different sample counts. There are 2 parameters:

  • directionCount: The number of directions in which to raytrace away from a given pixel
  • stepCount: The number of steps to take in the ray tracing along a given pixel

See this local Sandcastle for a demonstration of the parameters.

Is the code ready for review yet, or should we wait for the uniform changes to go in first?

I think it would make sense to wait until the uniform changes are done. I still have one change to implement: the step size should be automatically computed from the window size (lengthCap) and stepCount. This will take a little more thought since the step size is in pixels, while the Gaussian window is currently defined in meters.

sampleDirection = rotateStep * sampleDirection;

float localAO = 0.0;
float accumulatedWindowWeights = 0.0;
//vec2 radialStep = stepLength * sampleDirection;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
//vec2 radialStep = stepLength * sampleDirection;

@@ -51,11 +60,11 @@ void main(void)
}

vec3 normalEC = getNormalXEdge(positionEC);
float gaussianVariance = lengthCap * sqrt(-positionEC.z);
// TODO: mix of units. Steps are in pixels; variance is in meters.
Copy link
Contributor

Choose a reason for hiding this comment

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

Does czm_metersPerPixel help at all here?

@ggetz
Copy link
Contributor

ggetz commented Nov 21, 2024

@jjhembd I'm consistently seeing a band along the top of the screen, any idea what may be causing that? Is it the transition between multiple frustums maybe?

image

@ggetz
Copy link
Contributor

ggetz commented Nov 21, 2024

I'm also seeing some flickering due to occlusion when I look up at the sky. Is that just me?

@ggetz
Copy link
Contributor

ggetz commented Nov 21, 2024

@jjhembd What's the plan for blur? I noticed your sandcastle disables it entirely.

I agree the look of the blur is not great. Would it make sense to remove it completely? Maybe we could use MSAA to remove "noise" from few samples?

@ggetz
Copy link
Contributor

ggetz commented Nov 21, 2024

I'm seeing good results and a stable 60 FPS with

  stepCount: 32,
  directionCount: 8,

I think stepCount could potentially go even lower to 16, if we're looking fewer samples overall, and still look good.

That looks to be working well at other scales as well, such as buildings:

image

No AO, for comparison:
image

@jjhembd
Copy link
Contributor Author

jjhembd commented Nov 22, 2024

@ggetz thanks for the initial feedback!

I reworked the uniforms to compute the step length from the window size and step count. This value also works as the scalar to account for discrete sampling of the Gaussian, so we don't have to compute normalization factors in the inner loop.

I'm consistently seeing a band along the top of the screen

This does look like a frustum boundary. The occlusion should be neglecting this, since it appears in the depth buffer as a huge jump--much bigger than the window length. It's possible we're not correctly handling zero values in the depth buffer. I'm looking at this now.

What's the plan for blur?

We discussed using a bilateral filtering at one point, which would better preserve edges. I will take a look today to see how much work that would be.

We still need to add some kind of deprecation for the old uniform names. I updated the TODO list in the description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ambient Occlusion doesn't work!
2 participants