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

Merged
merged 21 commits into from
Dec 2, 2024
Merged

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

When viewing a scene from larger distances, some flickering and noise may be visible, partly due to #11067. These can be reduced by setting Viewer.camera.frustum.near to 1.0 or more, to improve precision in the depth buffer.

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.

@jjhembd jjhembd marked this pull request as ready for review November 26, 2024 23:47
@jjspace
Copy link
Contributor

jjspace commented Nov 27, 2024

@jjhembd I'm seeing some flickering across the entire terrain as I zoom out in the sandcastle. I'm also seeing some banding on the smokestack things but I'm not sure if those are related. The flicker is quick and goes away when the camera settles but is that expected?

simplescreenrecorder-2024-11-27_16.01.57.mp4

Copy link
Contributor

@jjspace jjspace left a comment

Choose a reason for hiding this comment

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

This is definitely a nice change to be able to see the AO from further away. I think the code looks good with my somewhat limited shader knowledge. I just had one small comment about the JS code. Also the bug(?) that I pointed out in my comment above

Comment on lines +101 to +102
forcePowerOfTwo = false,
sampleMode = PostProcessStageSampleMode.NEAREST,
Copy link
Contributor

Choose a reason for hiding this comment

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

This method of setting default values is not equivalent to the previous defaultValue calls when the value is null. I just want to make sure that's intended
2024-11-27_16-12

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jjspace agreed. I think we are already doing this in other parts of the code, with the assumption that null is only an issue when we might be passing the result of a document.getElement?? call or similar.
(and for others reading this, we have more discussion in #12196).

@jjhembd
Copy link
Contributor Author

jjhembd commented Dec 2, 2024

@jjspace thanks for the review!

I'm seeing some flickering across the entire terrain as I zoom out in the sandcastle.

I think this is related to #11067 (comment). We will still need to investigate the depth stability further, but I think we can leave that as a separate issue--let me know if that approach makes sense to you.

I'm also seeing some banding on the smokestack things

When using the log depth buffer with a very small value for the near plane (as is default), there is some inaccuracy in the far-away depth values. I just pushed an adjustment to the Sandcastle to push the near plane out to 1m. Does this reduce the artifacts on your end?

@jjspace
Copy link
Contributor

jjspace commented Dec 2, 2024

We will still need to investigate the depth stability further, but I think we can leave that as a separate issue--let me know if that approach makes sense to you.

I think I'm ok with that. I think I agree that benefit of ao at more distances outweighs the slight flickering at certain heights. Hopefully we can swing back around to that depth plane sooner than later though.

I just pushed an adjustment to the Sandcastle to push the near plane out to 1m. Does this reduce the artifacts on your end?

It does, the smokestacks look good. It also seems to reduce the other flickering issue pretty significantly. Would it make sense to change the overall default?

@jjhembd
Copy link
Contributor Author

jjhembd commented Dec 2, 2024

@jjspace adjusting the default near plane distance might have negative impacts on some other uses, where we need to render things close to the camera.
I updated both this PR description and CHANGES.md to recommend a larger near plane distance when AO at large distances is desired.

I also pushed a minor edit to ConvolveSpecularMapFS (from #12129) to fix an error showing up in WebGL1 contexts.

Thanks again for your feedback! I think this should be ready to go now.

Copy link
Contributor

@jjspace jjspace left a comment

Choose a reason for hiding this comment

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

Thanks @jjhembd! As discussed offline I think I agree that this is fine to go with the depth buffer issues which will need to be addressed as part of a larger effort for all post processing. I'm ok to merge this now

@jjspace jjspace added this pull request to the merge queue Dec 2, 2024
Merged via the queue into main with commit f0cec41 Dec 2, 2024
9 checks passed
@jjspace jjspace deleted the ao-sampling-disc branch December 2, 2024 17:06
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!
3 participants