Skip to content

Move MaterialX sheen BSDF into BSDL#2084

Open
aconty wants to merge 1 commit intoAcademySoftwareFoundation:mainfrom
aconty:sheen
Open

Move MaterialX sheen BSDF into BSDL#2084
aconty wants to merge 1 commit intoAcademySoftwareFoundation:mainfrom
aconty:sheen

Conversation

@aconty
Copy link
Contributor

@aconty aconty commented Mar 3, 2026

Description

Consolidate sheen implementation from testrender and SPI into a single BSDL-backed MaterialX lobe (mtx::SheenLobe), so sheen behavior is defined in one place and reused consistently across paths.

  • Move sheen logic into BSDL/MTX and wire it through the BSDL closure path
  • Replace ad-hoc testrender-side handling with the new BSDL implementation
  • Keep Conty/Zeltner mode selection inside the unified sheen lobe
  • Update sheen tests and references to validate the new path
  • Turn the furnace sheen test into a true energy-conservation check (sheen layered over white diffuse should converge to flat gray)

Proposal

At imageworks we scale up the Zeltner LTC sheen by 1 / max(albedo) = 0.74973. So a ~1.33 scale to match the other sheen maximum brightness of 1.0. This is very useful for artists not to perceive an energy loss from model to model. I suggest we do this at the MaterialX level too.

If people don't disagree I'll modify this PR to apply that scale.

Tests

Everything looking good. I moved the alpha = sqrt(roughness) mapping under the hood so you don't need special treatment for mode == 1. But I understand (more or less) if you don't like this and want me to revert that.

Checklist:

  • I have read the contribution guidelines.
  • I have updated the documentation, if applicable.
  • I have ensured that the change is tested somewhere in the testsuite (adding new test cases if necessary).
  • My code follows the prevailing code style of this project. If I haven't
    already run clang-format v17 before submitting, I definitely will look at
    the CI test that runs clang-format and fix anything that it highlights as
    being nonconforming.

@aconty
Copy link
Contributor Author

aconty commented Mar 3, 2026

Well, not very convinced about scaling up ZeltnerBurley since it is overall brighter already:

As it is now:
sheen1_vd8

With the 1.33 scale:
sheen2_vd8

Right side is Zeltner. The scale would just make maximum albedo 1.0 (more predictable?) I'm ok either way.

@aconty aconty force-pushed the sheen branch 2 times, most recently from 6758c6b to f70a628 Compare March 3, 2026 16:28
@fpsunflower
Copy link
Contributor

I would vote against modifying the Zeltner lobe. The model is already in use in a bunch of places (including OpenPBR) with the default implementation straight from the paper.

Its meant to represent a thin layer of fuzz with unit mfp - its expected that it does not reach an albedo of 1.

Copy link
Contributor

@fpsunflower fpsunflower left a comment

Choose a reason for hiding this comment

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

LGTM overall.

static constexpr bool FITTED_LTC = false;

// LTC sampling is weak at low roughness, gains energy, so we clamp it.
static constexpr float MIN_ROUGHNESS = LTC_SAMPLING ? 0.1f : 0.0f;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm curious how you found the limit of 0.1 - in another implementation I wrote I had a limit of 0.02 which seems to work fine with LTC sampling.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By trial and error with the furnace test. Below that you can see some energy gain. It doesn't happen with uniform sampling though. Maybe your LTC sampling is more numerically stable.

So I went back to how the SPI code and the github paper repo works. I recovered the numerical stability and is less error prone now. Was able lo lower the min roughness to your chosen 0.02.

Consolidate sheen implementation from testrender and SPI into a single
BSDL-backed MaterialX lobe (`mtx::SheenLobe`), so sheen behavior is defined
in one place and reused consistently across paths.

- Move sheen logic into BSDL/MTX and wire it through the BSDL closure path
- Replace ad-hoc testrender-side handling with the new BSDL implementation
- Keep Conty/Zeltner mode selection inside the unified sheen lobe
- Update sheen tests and references to validate the new path
- Turn the furnace sheen test into a true energy-conservation check
  (sheen layered over white diffuse should converge to flat gray)

AI Disclaimer: AI has been used to code review and bug hunt, but all the
code and fixes have been written by huomans.

Signed-off-by: Alejandro Conty <aconty@imageworks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants