Skip to content

Fix #22574: fix volumetric fog back-face intersection artifacts#23588

Open
joaoconceicao12 wants to merge 5 commits into
bevyengine:mainfrom
joaoconceicao12:fix-fogvolume-22574-main
Open

Fix #22574: fix volumetric fog back-face intersection artifacts#23588
joaoconceicao12 wants to merge 5 commits into
bevyengine:mainfrom
joaoconceicao12:fix-fogvolume-22574-main

Conversation

@joaoconceicao12
Copy link
Copy Markdown

Objective

Fixes #22574.

This PR fixes angle-dependent volumetric fog artifacts in the atmosphere example ([--features free_camera], where rotating the camera caused shadow flipping and hard edges.

Solution

The root cause was inconsistent back-face intersection setup between CPU and shader paths:

CPU side: far-plane construction for fog volume traversal.
WGSL side: ray-plane intersection math.

This PR:

Corrects far-plane setup in the volumetric fog CPU path.
Corrects the WGSL ray-plane intersection calculation.
Adds a regression unit test for [get_far_planes]) to prevent this from regressing.

Testing

cargo test -p bevy_pbr --lib passes (including the new regression test).
Manual visual test:
cargo run -r --example atmosphere --features free_camera
Rotating the camera no longer shows the previous flipping/hard-edge artifacts. (see video)

video1.mov

Platform tested:
macOS (Metal backend).
No additional untested platform-specific behavior is currently known.Fixes angle-dependent volumetric fog artifacts in the atmosphere example (shadow flipping and hard edges while rotating the camera).

@joaoconceicao12
Copy link
Copy Markdown
Author

Follow up target branch correction from PR #23406

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 30, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Rendering Mar 30, 2026
@alice-i-cecile alice-i-cecile added X-Uncontroversial This work is generally agreed upon D-Straightforward Simple bug fixes and API improvements, docs, test and examples labels Mar 30, 2026
Copy link
Copy Markdown
Contributor

@mate-h mate-h left a comment

Choose a reason for hiding this comment

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

This change breaks the fogvolume during my testing (no longer visible.)

@joaoconceicao12
Copy link
Copy Markdown
Author

The issue was happening on the release-0.18.0 branch(that is why my target branch was this branch in the other PR) and so was my solution for this based on it. In the older branch the atmosphere display a fog box volume that made the bug appear clearly.
Since then the example has been modified and no longer shows fog. Im modifying the example to making it possible to see the fog box volume as it appeared on the issue.

@joaoconceicao12 joaoconceicao12 force-pushed the fix-fogvolume-22574-main branch from 8486bdb to 56aead8 Compare April 5, 2026 16:53
@mate-h
Copy link
Copy Markdown
Contributor

mate-h commented Apr 5, 2026

Thanks for the due dilligence - we never modified the example to remove the fog. Here are the lines in the example that add it to the scene: https://github.com/joaoconceicao12/bevy/blob/fix-fogvolume-22574-main/examples/3d/atmosphere.rs#L231-L235

So there must be something with this change set in this pull requests that makes it not work anymore. The render pass executes (checked this with xcode debugger) but the location of the rendered fogvolume is wrong.

@joaoconceicao12
Copy link
Copy Markdown
Author

joaoconceicao12 commented Apr 7, 2026

Thanks for the heads up you were right about the issue in rendering.

After tracing the issue, i found the problem was in the volumetric fog intersection math, not in scene setup:

  • CPU side far-plane selection could become unstable with camera orientation, which affected the back-face intersection basis.
  • Shader side ray setup/marching in view space produced angle-dependent behavior, causing hard edges and shadow flipping while rotating.

The fix updates both paths:

  • Deterministic far-plane selection and interior-state hysteresis on CPU side.
  • Corrected ray-plane intersection usage and view-space sampling origin in WGSL.

I also recorded a video showing the example running with this patch and camera rotation, to demonstrate that the issue no longer happens. (increased density_factor for better visualization)

video2.mov

Sorry for the delay im currently finishing my bachelor's degree at IST and exam week is coming up.

fn camera_is_inside_fog_volume_hysteresis(local_from_view: &Affine3A, was_inside: bool) -> bool {
// Entering interior requires being slightly deeper than the boundary,
// while leaving interior requires being slightly further outside.
const ENTER_THRESHOLD: f32 = 0.495;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These threshold values seem arbitrary. I think fundamentally we shouldn't distinguish between is inside and is outside volume, instead just fix the ray-plane intersection tests in the shader.

@mate-h
Copy link
Copy Markdown
Contributor

mate-h commented Apr 7, 2026

I appreciate all your efforts. Tested the example again, while I can see it from outside the fog volume, the fog seems to fade out when I get close with the camera, and when the camera is inside the volume it's not visible at all. This change/fix seems to be heading in the wrong direction. If you're busy - I could look into fixing it if you want to prioritize this issue! Also make sure to review our AI policy.

@joaoconceicao12
Copy link
Copy Markdown
Author

joaoconceicao12 commented Apr 7, 2026

Thanks for the feedback. Being honest i wasn't really sure on how FogVolume should behave when the camera is inside it or when approaching it that's my mistake for not expressing my doubt. I don't like delivering a half-done job so i will continue working to fix the problems you mentioned.
Thanks

@joaoconceicao12
Copy link
Copy Markdown
Author

Im having some doubts about the expected behaviour for the FogVolume seeing it from the outside. Could you explain its behaviour?
Is it supposed to have a kind of like fading effect (opacity decreasing in borders) or is it supposed to have the borders clearly visible?

@mate-h
Copy link
Copy Markdown
Contributor

mate-h commented Apr 11, 2026

That depends but the borders of the fogvolume should generally remain visible when not using a custom density texture. Any camera ray that hits the fog volumes bounding box will travel a non zero distance that is then attenuated with the beer lambert law to render it. Any kind of fading with distance is a rendering artifact. The only fading that should happen is when the ray travels less in the volume that is the camera is inside looking at and approaching the end of the bounding volume. Hope this clears things up !

@alice-i-cecile
Copy link
Copy Markdown
Member

@JeroenHoogers, your expertise from #23887 would also be welcome here :)

…acts

Fixes angle-dependent volumetric fog artifacts in the atmosphere example
(shadow flipping and hard edges while rotating the camera).

Root cause was inconsistent back-face intersection setup: far-plane
construction in CPU code and ray-plane intersection in WGSL shader code.

This patch corrects both calculations and adds a regression test for
far-plane positioning in volumetric fog (get_far_planes).

Signed-off-by: João Conceição <joao.conceicao@tecnico.ulisboa.pt>
…acts

Fixes angle-dependent volumetric fog artifacts in the atmosphere example (shadow flipping and hard edges while rotating the camera).

Root cause was inconsistent back-face intersection setup across CPU and shader paths: far-plane selection instability in CPU code and ray marching/view-space sampling inconsistencies in WGSL shader code.

This patch makes far-plane selection deterministic, adds inside/outside hysteresis near fog boundaries, and corrects shader ray-plane intersection usage and view-space sampling origin.

Signed-off-by: João Conceição <joao.conceicao@tecnico.ulisboa.pt>
This commit fixes the volumetric fog fading when aproaching and when inside of it. It also removes threshold values.

Signed-off-by: João Conceição <joao.conceicao@tecnico.ulisboa.pt>
Fixes fog fading when leaving the Volume looking toward its end boundary. Also fixed black sky inside the FogVolume when leaving(view_end_depth_from_buffer was very far making it over-attenuated making the sky dark)

Signed-off-by: João Conceição <joao.conceicao@tecnico.ulisboa.pt>
@JeroenHoogers
Copy link
Copy Markdown
Contributor

While I really appreciate the efforts to fix this issue, I think this is not the correct approach. Especially the boundary fading logic seems undesirable and will produce non-physically accurate results. Like @mate-h suggested earlier, the fix should be limited to fixing the problems with the intersection tests.

Given the back and forth on this fix already I think it is worth discussing whether this is the right path to follow. I'd be happy to look into this and explore alternatives.

@alice-i-cecile alice-i-cecile added S-Nominated-To-Close A triage team member thinks this PR or issue should be closed out. and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels May 5, 2026
@alice-i-cecile
Copy link
Copy Markdown
Member

@JeroenHoogers I'd be keen to see another PR with that approach.

@JeroenHoogers
Copy link
Copy Markdown
Contributor

@alice-i-cecile @mate-h I fixed it here #24220

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-Bug An unexpected or incorrect behavior D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Nominated-To-Close A triage team member thinks this PR or issue should be closed out. X-Uncontroversial This work is generally agreed upon

Projects

Status: Needs SME Triage

Development

Successfully merging this pull request may close these issues.

FogVolume is glitchy at distances and certain angles on example.

5 participants