Repository navigation
Conversation
…ftwareFoundation#314) Replace clamp(specular_weight * F82, 0, 1) with a formulation expressible in the MaterialX graph: specular_weight <= 1 scales the whole metal lobe (unchanged), while specular_weight > 1 boosts the F0 and F82 edge-tint colors, each clamped to [0, 1]. The result is always a valid F82-tint Fresnel curve bounded in [0, 1]. The MaterialX graph drives the generalized_schlick_bsdf weight, color0 and color82 inputs accordingly, and the Emetal coat-darkening estimate now uses the boosted F0 (which also includes base_weight). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
jamportz
added a commit
to jamportz/OpenPBR
that referenced
this pull request
Sep 23, 2026
…amp) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
jamportz
marked this pull request as ready for review
September 23, 2026 20:47
This was referenced Sep 29, 2026
jstone-lucasfilm
approved these changes
Sep 29, 2026
jstone-lucasfilm
left a comment
Member
There was a problem hiding this comment.
This looks great to me, @jamportz, and clamping before the BSDF evaluation should work well in MaterialX/OSL/MDL.
One minor, non-blocking suggestion for the specification text: the statement that the curve "tends to a perfect (white) mirror as specular_weight -> inf" holds only where the colors are non-zero. Since the boost is multiplicative, a zero channel in specular_color would stay at zero for any specular_weight, so the edge reflectance in that channel would remain pinned at zero.
Perhaps this could be qualified as "tends to a perfect (white) mirror as specular_weight -> inf, for non-zero colors"?
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #314.
Summary
In v1.2 (#238) the metallic Fresnel is$\mathrm{clamp}(\xi_s \mathbf{F}_{82}(\mu), 0, 1)$ , where $\xi_s$ = $\xi_s$ , and for $\xi_s > 1$ it reflects more light than it receives (see the furnace test below).
specular_weight. The MaterialX graph can't express this clamp, because the Fresnel is evaluated insidegeneralized_schlick_bsdf. So the reference graph just sets the lobeweighttoAs discussed in the meeting, this PR instead clamps the two colors that parametrize the F82-tint curve:
where$\mathbf{F}_{82}(\mu)$ is the existing F82-tint curve, built from the colors
weight,color0andcolor82inputs ofgeneralized_schlick_bsdf.A footnote records an equivalent form for generalized-Schlick implementations:$\mathbf{F}_0 = \min(\xi_s \mathtt{base\_weight} \mathtt{base\_color}, 1)$ and $\mathbf{F}_{90} = \min(\xi_s, 1)$ , with no lobe weight. This works because $\mathbf{C}_s$ is relative to the Schlick curve, so scaling the whole curve by $\xi_s \le 1$ is the same as scaling $\mathbf{F}_0$ and $\mathbf{F}_{90}$ .
Changes
index.html):specular_weightdescription in the metal parameter table.reference/open_pbr_surface.mtlx): addedmetal_weightmetal_boostmetal_F0andmetal_F82, and wired them into all four metalgeneralized_schlick_bsdfnodes (base, thin-film, haze, haze + thin-film).Emetalis nowmetal_weight * metal_F0base_weightintoEmetal; previously it usedbase_coloralone.CHANGELOG.md: added an entry.Furnace test
A smooth ($\mathtt{specular\_roughness} = 0$ ) metal sphere in a uniform white environment of radiance 1. Each pixel is then exactly $\mathbf{F}_{\mathrm{metal}}(\mu)$ , so anything brighter than the background creates energy. The images are shown one stop down, so the background is mid-grey. "max" is the largest pixel value in the image; the background is 1, so a physical result has max = 1. All renders use the MaterialX graph compiled to OSL and rendered in Arnold.
Rows: v1.2 graph is the current graph (unclamped); A boosts$\mathbf{F}_0$ only; B (this PR) boosts $\mathbf{F}_0$ and $\mathbf{C}_s$ ; C boosts $\mathbf{F}_0$ and the absolute 82° reflectivity (see "Alternatives considered").
Gold:$\mathtt{base\_color} = (1, 0.72, 0.315)$ , $\mathtt{specular\_color} = (1, 0.973, 0.597)$
graph
max 1.00
max 2.00
max 4.00
max 8.00
max 1.00
max 1.00
max 1.00
max 1.00
(this PR)
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
Tinted metal:$\mathtt{base\_color} = (0.5, 0.5, 0.5)$ , $\mathtt{specular\_color} = (0.3, 0.55, 0.9)$
graph
max 1.00
max 1.60
max 3.18
max 6.35
max 1.00
max 1.00
max 1.00
max 1.00
(this PR)
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
max 1.00
The old graph glows once$\xi_s > 1$ : the sphere becomes brighter than the environment illuminating it, with pixel values up to about $\xi_s$ . A, B and C never exceed the background. As $\xi_s$ grows they tend to a perfect white mirror, which is correctly invisible in a furnace. The differences between A, B and C are confined to a thin band at the silhouette (82° maps to the outer ~1% of the sphere's radius), so they are compared using the Fresnel curves under "Alternatives considered".
Shader ball (gold, roughness 0.2)
Same rows as above.
graph
(this PR)
Alternatives considered
All three options below are identical for$\xi_s \le 1$ ; they differ only in the edge tint used for $\xi_s > 1$ .
Analytic Fresnel curves for single channels, compared with the old$\xi_s \mathbf{F}_{82}$ graph and the v1.2 spec clamp:
🤖 Generated with Claude Code