Skip to content

Conversation

@portsmouth
Copy link
Contributor

@portsmouth portsmouth commented Jun 24, 2025

According to the discussion in #239 (and on Slack), we need to provide a less obviously wrong suggestion for the coat roughening effect.

I wrote up the formula for the IOR dependence suggested by @peterkutz (with my simplification applied):

image

According to the discussion in #226, we also need to provide some suggested approximation for the roughening effect of fuzz.

I wrote up the formula I proposed, based on feedback from @peterkutz and @virtualzavie.

image

In my Arnold test implementation, I also had $R_F$ multiplied by the fuzz_roughness parameter, but on reflection that seems unjustified, since the reasoning is supposed to be that the roughening is being approximated/proxied by the reflection albedo (times tint), which is a function of the fuzz_roughness (so no need for an extra factor of fuzz_roughness). Intuitively, if fuzz_roughness is low, the microflakes are thin fibres which scatter very little so light normally incident travels more-or-less straight through undeflected, except near grazing where a forest of fibres is visible so the resulting albedo is significant, so such low fuzz_roughness fuzz will roughen the base only when viewed near grazing.

I will re-do my renders of the effect to check what visible difference this makes.

I'll note these formulas (particularly the one for fuzz) are obviously just generated purely out of (educated) guesswork. Possibly we should add some caveat noting that, though we do say they are just approximations. The use of the luminance of the tint to get a scalar roughening seems particularly flaky. It still seems worth suggesting them, as without them implementations have no guidance, and the resulting look will be less plausible.

Ideally we would have a better sense of how bad the approximations are, by comparing to some data/simulations, and develop more principled fits. We're working on that. (And if we do develop better approximations, we should eventually move them into our tech report, rather than provide the details in the spec itself).

@portsmouth portsmouth changed the base branch from main to dev_1.2 June 24, 2025 02:30
@portsmouth portsmouth changed the base branch from dev_1.2 to dev_1.1.1 June 24, 2025 02:30
@portsmouth portsmouth changed the base branch from dev_1.1.1 to dev_1.2 June 24, 2025 02:31
@portsmouth
Copy link
Contributor Author

portsmouth commented Jun 24, 2025

I think we need to think a bit about what the effect of the fuzz tint color should be.

With the roughening heuristic above, I get the following results when the fuzz color is varied from light to dark.

light fuzz dark fuzz
new_r1 0 new_colored_r1 0

When the fuzz is dark, our heuristic reduces the roughening, so we see a sharp highlight.
However, I think we were assuming that dark fuzz (with high weight and roughness), should produce dark fuzzy patches, not just look transparent. This doesn't happen though, because the color only modulates the fuzz reflection, it does not alter the throughput/transmittance to the base.

I find that a bit unconvincing as if the fuzz is same density in the left and right image, you would expect the highlight to be much more dimmed on the right. In reality, more absorbing dust should reduce the transmittance as well as the reflection. It may be inherent in the Zeltner model though, that this more realistic volumetric absorption isn't really captured.

The effect of the coat roughening can then be modeled as the convolution of these Gaussian NDFs, which corresponds to adding the variances (double counting the coat variance since the reflection passes through the coat boundary twice). The IOR ratio of the coat and ambient medium $\eta_\mathrm{ca}$ also needs to be accounted for, since as $\eta_\mathrm{ca} \rightarrow 1$ the roughening due to the coat goes to zero.
This leads to the following suggested approximate formula for the modified roughness $r'_\mathrm{B}$ of the base due to the coat:
\begin{equation} \label{coat_roughening_heuristic}
r'_\mathrm{B} = \mathrm{min} \bigl(1, r^4_\mathrm{B} + 2 x_C r^4_\mathrm{C} \bigr)^\frac{1}{4} \quad \textrm{with } x_C = 1 - \mathrm{min}(\eta_\mathrm{ca}, 1/\eta_\mathrm{ca})
Copy link
Contributor

Choose a reason for hiding this comment

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

Does "x" mean something or is it just an arbitrary available variable name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just a variable name. It accounts for the IOR, so not sure what symbol to use. Putting the min inside the brackets looked worse.

@peterkutz
Copy link
Contributor

Regarding the effect of dark fuzz in the images, I think the

I find that a bit unconvincing as if the fuzz is same density in the left and right image, you would expect the highlight to be much more dimmed on the right. In reality, more absorbing dust should reduce the transmittance as well as the reflection. It may be inherent in the Zeltner model though, that this more realistic volumetric absorption isn't really captured.

True. The Zeltner model is based on non-absorbing microflakes and it doesn't make a distinction between scattered and unscattered transmission. So some of the transmitted light is actually scattered light that should be eliminated if the single-scattering albedo of the microflakes is zero. So I agree that the dark fuzz should technically darken the base surface more. That said, in your renders it's hard to see how much the dark fuzz is actually darkening the base because the specular highlight is overexposed and the background is black.

\mu_i \, f_\mathrm{fuzz}(\omega_i, \omega_o) = \mathbf{F} \, E_\mathrm{fuzz}(\mu_o, r_F) \, D(\mu_i | \mu_o, r_F)
\end{equation}
where $\mathbf{F}$ = **`fuzz_color`**, $E_\mathrm{fuzz}(\mu_o, \alpha)$ (termed $R$ in [#Zeltner2022]) is the reflectance at angle cosine $\mu_o$ given roughness $\alpha$ = **`fuzz_roughness`** $\in [0,1]$, and $D(\mu_i | \mu_o, \alpha)$ is a lobe defined by linear transformations of a cosine lobe (LTCs), where the transformation matrices (and $E_\mathrm{fuzz}$) are tabulated in a grid in the $(\mu_o, \alpha)$ plane, with values fitted to a simulation of the scattering in the volumetric fuzz microflake layer. Since the LTC lobe $D$ is a normalized PDF over the hemisphere, the resulting albedo of $f_\mathrm{fuzz}$ is $\mathbf{F} \, E_\mathrm{fuzz}(\mu_o, \alpha)$.
where $\mathbf{F}$ = **`fuzz_color`**, $E_\mathrm{fuzz}(\mu_o, r_F)$ (termed $R$ in [#Zeltner2022]) is the reflectance at angle cosine $\mu_o$ given roughness $r_F$ = **`fuzz_roughness`** $\in [0,1]$ (termed $\alpha$ in [#Zeltner2022]), and $D(\mu_i | \mu_o, r_F)$ is a lobe defined by linear transformations of a cosine lobe (LTCs), where the transformation matrices (and $E_\mathrm{fuzz}$) are tabulated in a grid in the $(\mu_o, r_F)$ plane, with values fitted to a simulation of the scattering in the volumetric fuzz microflake layer. Since the LTC lobe $D$ is a normalized PDF over the hemisphere, the resulting albedo of $f_\mathrm{fuzz}$ is $\mathbf{F} \, E_\mathrm{fuzz}(\mu_o, r_F)$.
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume you're using different variables than the Zeltner paper to be consistent with other formulas in the OpenPBR spec. Is that right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, since $\alpha$ means roughness squared in the microfacet case, so it could be a bit confusing to use the same symbol here.

The scattering within the fuzz layer will have the effect of roughening the appearance of the substrate beneath it.
A simple suggested approximation for this can be adapted from the formula used to model the coat roughening, in equation [coat_roughening_heuristic]. If we consider the fuzz layer to generate roughening by scattering, we can approximate its effective roughness as being proportional to the albedo of the layer, as well as to the tint color (since darker fuzz will physically scatter less and absorb more). This leads to the following heuristic for the modified roughness $r'_\mathrm{B}$ of the substrate lobe:
\begin{equation} \label{fuzz_roughening_heuristic}
r'_\mathrm{B} = \mathrm{min} \bigl(1, r^4_\mathrm{B} + 2 R^4_\mathrm{F} \bigr)^\frac{1}{4} \quad \textrm{with $R_F = \mathrm{lum}(\mathbf{F} E_\mathrm{fuzz})$}
Copy link
Contributor

Choose a reason for hiding this comment

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

The inclusion of E_fuzz here means that the roughening will be more intense at grazing angles where the optical density is higher, correct?

Copy link
Contributor

Choose a reason for hiding this comment

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

The fuzz doesn't use a GGX distribution like the coat, so I wonder whether these fourth powers are still justifiable.

Based on my own empirical testing, I had to tone down the fuzz roughening quite a bit (compared to coat roughening) to get it to look plausible.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, the E_fuzz functions almost like a coverage weight, since it's essentially the opacity of the fuzz layer, so intuitively it seems like the blending based on E_fuzz (and maybe the color F too) should be a simple lerp on the final roughness (unaffected by the powers and roots).

Copy link
Contributor Author

@portsmouth portsmouth Jul 6, 2025

Choose a reason for hiding this comment

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

The inclusion of E_fuzz here means that the roughening will be more intense at grazing angles where the optical density is higher, correct?

Yes true.

The fuzz doesn't use a GGX distribution like the coat, so I wonder whether these fourth powers are still justifiable.

The $E_\mathrm{fuzz}$ term is the albedo of the fuzz layer (in the Zeltner sims), i.e. (presumably) what fraction of the light is reflected back as opposed to transmitted through.

So I am just loosely assuming that this albedo can be a sort of proxy of the "amount of scattering", and thus the amount of roughening captured in a roughness scalar $R_F$.

If the roughening is some (angular) Gaussian blurring with the angular blur varying with $R_F$ in the same way as the GGX blurring, then the combination with the base roughness (with the fourth powers) is a reasonable guess. Though agreed there's no very good rationale for that assumption, currently. There could easily be some multiplicative factor required to compare the "fuzz roughening" to the GGX roughness, or possibly the effect is totally different to the proposed formula even with such an adjusted factor.

We'll need to do some simulations to check how it compares to reality, and fix it up accordingly.

E_fuzz functions almost like a coverage weight, since it's essentially the opacity of the fuzz layer

Not sure I agree, since as noted it's really the albedo (varying with input direction). The coverage (and opacity) is constant in the Zeltner model, i.e. unit optical depth of fuzz.

Obviously we also have the fuzz weight, functioning as an actual coverage weight, which should affect the roughening.

@peterkutz
Copy link
Contributor

Great to have the IOR officially included in the spec's coat roughening formula and a mention of fuzz roughening.

Conceptually, the form of the fuzz roughening is questionable compared to coat roughening. The coat has a refractive interface, so all light passing through it is scattered. But the fuzz is effectively a volume without an interface, so only some of the transmitted light is scattered. The fuzz should ideally produce a mixture of roughened and un-roughened base lobes. Plus the scattering distribution should ideally be different due to the anisotropic scattering of the fuzz.

So, I wonder if a stochastic selection of roughened and un-roughened base roughness (based on a rough estimate of the scattered/unscattered transmission of the fuzz) would produce better results. (The proposed specular haze could potentially be leveraged to roughen only a fraction of the light, but the haze might already be in use.)

@portsmouth
Copy link
Contributor Author

Totally agree that we need to do more work on both of these formulas to produce the best approximation we can offer. For this we are going to need a combination of theory and simulation. I’m hoping we can work on this in the coming weeks as part of the preparation for the siggraph presentation. Even if it doesn’t make it into the presentation, we probably have enough time (say till the end of the year) to come up with a more physically based model for the 1.2 release.

@AdrienHerubel AdrienHerubel marked this pull request as draft September 30, 2025 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants