Skip to content

Fix energy loss in multi-scattering term#23203

Merged
alice-i-cecile merged 5 commits into
bevyengine:mainfrom
dylansechet:fix_multiscattering
Mar 5, 2026
Merged

Fix energy loss in multi-scattering term#23203
alice-i-cecile merged 5 commits into
bevyengine:mainfrom
dylansechet:fix_multiscattering

Conversation

@dylansechet

@dylansechet dylansechet commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Objective

With #23194 applied, the white furnace test passes for pure metals and dielectrics, but fails for anything in between.

Solution

The issue seems to be the multi-scattering term used in environment_map_light.
The current code computes FmsEms(mix(F0_dielectric, F0_metal, metalness)) when it should be computing mix(FmsEms(F0_dielectric), FmsEms(F0_metal), metalness), which causes an issue as FmsEms is non-linear in F0.

The bug is also present in the blogpost that was used as inspiration for the implementation, where the author mentions that the results with multi-scattering are darker than they should be.

Testing

  • Ran cargo run --example testbed_white_furnace. I've never been so happy to see a gray image :)
  • Ran cargo run --example pbr.

Showcase

White furnace test (with #23194 also applied):

Before:
fix_vndf

After:
fix_multiscatter+vndf

PBR test also on imgsli

Before:
main

After:
this_pr

@alice-i-cecile alice-i-cecile added this to the 0.19 milestone Mar 3, 2026
@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen C-Refinement Improves output quality, without fixing a clear bug or adding new functionality. labels Mar 3, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Rendering Mar 3, 2026
@alice-i-cecile alice-i-cecile added D-Straightforward Simple bug fixes and API improvements, docs, test and examples D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed D-Straightforward Simple bug fixes and API improvements, docs, test and examples labels Mar 3, 2026
@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-23203

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

@alice-i-cecile alice-i-cecile added the M-Release-Note Work that should be called out in the blog due to impact label Mar 3, 2026
@github-actions

github-actions Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

@alice-i-cecile

Copy link
Copy Markdown
Member

Successfully passing the white furnace test is an important milestone, and a neat thing to teach people about. Can you add a release note for this PR + #23194 as part of this PR?

If you're comfortable explaining the background of the test, why it's significant and what we were doing wrong, please do so, but just a stub is fine :)

@alice-i-cecile alice-i-cecile added the M-Deliberate-Rendering-Change An intentional change to how tests and examples are rendered label Mar 3, 2026
@mate-h mate-h self-requested a review March 3, 2026 17:58

@JMS55 JMS55 left a comment

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.

Awesome PR!

About passing the white furnace test; that's only true for the EnvMapLight code. Directional lights, point lights, spot lights, irradiance volumes, and probably other things I'm forgetting all go through their own paths, which are not tested in the current example.

@JMS55

JMS55 commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

I'm especially suspicious about several places where we directly add specular and diffuse contributions together, rather than mixing them based on the fresnel factor. I attempted to solve this in Solari by switching to OpenPBR's BRDF spec, but it didn't seem to make much of a difference, and I ultimately decided to prioritize other work.

@dylansechet if you're interested in discussing this (or Solari's other BRDF issues), please reach out on discord in #rendering-dev!

@mockersf

mockersf commented Mar 4, 2026

Copy link
Copy Markdown
Member

merging main in so that it triggers the white furnace in CI check

@mockersf

mockersf commented Mar 4, 2026

Copy link
Copy Markdown
Member

@mate-h mate-h left a comment

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.

Amazing work! This is all mathematically sound and I don't really have any blocking comments, just some general feedback on the readability. Ship it!


After fixing those, Bevy passes the test. That means your materials will behave more correctly under image-based lighting.

A gray image has never been so exciting! No newline at end of file

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.

Nice touch at the end haha

Comment thread crates/bevy_pbr/src/light_probe/environment_map.wgsl Outdated
Comment thread crates/bevy_pbr/src/light_probe/environment_map.wgsl Outdated
@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 4, 2026
@alice-i-cecile

Copy link
Copy Markdown
Member

I'm going to hold off a bit so you can review the non-blocking feedback @dylansechet. Let me know if you'd like me to just merge it though!

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 5, 2026
Merged via the queue into bevyengine:main with commit 1108f27 Mar 5, 2026
38 checks passed
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in Rendering Mar 5, 2026
authors: ["@dylansechet"]
pull_requests: [23194, 23203]
---
The [white furnace test](https://lousodrome.net/blog/light/2023/10/21/the-white-furnace-test/) is a classic sanity check for physically-based renderers. Place a perfectly reflective object inside a uniform white environment, and it should be indistinguishable from the background, no matter how metallic and rough. Any object that remains visible is a sign that the shader is creating or absorbing energy it shouldn't.

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.

Doesn't have to be perfectly reflective - all BRDFs should obey this.

Otherwise, great writing!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks!
I meant "perfectly reflective" in the sense that we need albedo = 1 for the object to disappear into. But I agree, it's a clumsy choice of words and should be changed in the final veersion.

@dylansechet dylansechet mentioned this pull request Apr 15, 2026
greeble-dev pushed a commit to greeble-dev/bevy that referenced this pull request May 21, 2026
# Objective

This PR is split off from bevyengine#23818.
It depends on bevyengine#24313, which is integrated as the first commit here. 

There's an issue in the solari BRDF which causes partially metallic
objects to lose energy in the white furnace test.

## Solution

The current BRDF computes a blended F0 between metallic and dielectric
materials, and then uses it it for calculations. It should be evaluating
both the metallic and dielectric BRDFs separately and only blend them as
a last step.

A similar issue used to be present for IBL and was fixed in the same
way, see bevyengine#23203.

## Showcase

### White furnace test

Main:
<img width="1280" height="720" alt="layering"
src="https://github.com/user-attachments/assets/5c7abaac-93ac-4a35-be76-e81681094232"
/>


This PR:
<img width="1280" height="720" alt="mixing"
src="https://github.com/user-attachments/assets/d0c32bab-c880-4222-a255-1f9a5c2e3f6a"
/>
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-Refinement Improves output quality, without fixing a clear bug or adding new functionality. D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes M-Deliberate-Rendering-Change An intentional change to how tests and examples are rendered M-Release-Note Work that should be called out in the blog due to impact S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants