AcademySoftwareFoundation / OpenPBR

Specification and reference implementation for the OpenPBR Surface shading model
Apache License 2.0
407 stars 18 forks source link

Merge specular_weight and specular_ior_level #152

Closed portsmouth closed 2 months ago

portsmouth commented 6 months ago

We had much discussion on Slack about how the layering (e.g. of the specular layer on the diffuse base) should be implemented in code, and described physically in the spec. We eventually came up with a proposal for a modification that clarifies and simplifies the model: to reinterpret specular_weight as the existing specular_ior_level, thus merging the two parameters and removing the latter from the model. (Also, removing coat_ior_level).

We originally settled on retaining both specular_weight and specular_ior_level from the ADSK and Adobe models as a sort of compromise solution. It seems though that it would be an improvement to merge them, both from the point of view of simplifying the user experience, and clarifying what the parameters are supposed to correspond to physically for implementers.

I try to summarize the discussion below (the background from Slack, then the proposal).


Background

Currently in the spec, we say about specular_weight that it functions as follows:

The specular_weight and specular_color parameters modulate the Fresnel factor of fdielectric. ... The light transmitted through the dielectric will be compensated accordingly to preserve the energy balance (thus generating a complementary color if specular_color is not white).

As discussed in https://github.com/AcademySoftwareFoundation/OpenPBR/issues/145, this intepretation of specular_color is problematic since it implies there will be a complementary color. So we will need to modify this to say that the specular_color only affects the reflection Fresnel factor, not the transmission.

But we also need to clarify what specular_weight does (in code, and physically). It actually doesn't make sense for specular_weight to only multiply the reflection Fresnel factor, since this would mean there would be darkening of the base even when specular_weight goes to zero. For example, in the case of the glossy-diffuse layer, this is supposed to be a layer of dielectric on top of a diffuse base. If specular_weight only modulates the reflection Fresnel factor, then dialing it to zero still generates darkening of the base due to the internal reflections in the layer, which are explicitly unaffected. In terms of the albedo-scaling approximation, specifying that the weight only multiplies the reflection Fresnel factor implies:

f_{\mathrm{glossy-diffuse}} \approx W \mathbf{C} f_{\mathrm{dielectric}} + \left(1 - E_{\mathrm{dielectric}}\right) \, f_{\mathrm{diffuse}}

where specular_weight $W$ and specular_color $\mathbf{C}$ multiply the first term. Then the $\left(1 - E_{\mathrm{dielectric}}\right)$ factor remains in the second term as specular_weight $W \rightarrow 0$, which produces darkening.

In standard surface, instead what we had was a formula like:

f_{\mathrm{glossy-diffuse}} \approx W \mathbf{C} f_{\mathrm{dielectric}} + \left(1 - W \mathbf{C} E_{\mathrm{dielectric}}\right) \, f_{\mathrm{diffuse}}

which ensures that as $W \rightarrow 0$, only the undarkened $f_{\mathrm{diffuse}}$ remains. Except, this generates the complementary color tint of the diffuse lobe.

It was proposed to alter this to (e.g. this is how MaterialX implements their dielectric layering):

f_{\mathrm{glossy-diffuse}} \approx W \mathbf{C} f_{\mathrm{dielectric}} + \left(1 - W E_{\mathrm{dielectric}}\right) \, f_{\mathrm{diffuse}}

Physically, this can be interpreted as meaning that the specular_weight is functioning as the presence weight of the dielectric layer (this interpretation leads to the formula above, in albedo-scaling approximation, as is easy to prove).

This makes some sense for the glossy-diffuse part of the specular lobe, but not really for the subsurface and transparent base, where the dielectric base is supposed to be the semi-infinite bulk. Putting this in a statistical superposition of present and absent is physically dubious (it also was for the glossy-diffuse layer really, as the dielectric was supposed to embed the diffuse medium, not just sit on top of it). So to use this presence interpretation of specular_weight we would have to specialize that to the glossy-diffuse case only, and say something different for the subsurface/transmission (e.g. that specular_weight reverts to being a non-physical multiplier of the Fresnel factor).


Simplification proposal

Rethinking the issue, Peter and I propose that we can achieve the desired the behaviour more simply just by having specular_weight function exactly as specular_ior_level does now, then omitting the latter parameter. That is, the specular_weight specifies a multiplier of the reflection Fresnel factor, achieved by modulating the IOR of the entire dielectric base. The corresponding albedo scaling formula will be:

f_{\mathrm{glossy-diffuse}} \approx \mathbf{C} f_{\mathrm{dielectric}} + \left(1 - E_{\mathrm{dielectric}}\right) \, f_{\mathrm{diffuse}}

as now the specular_weight $W$ functions by altering the IOR of $f{\mathrm{dielectric}}$ (thus the Fresnel factor). As $W \rightarrow 0$, the specular BRDF $f{\mathrm{dielectric}} \rightarrow 0$ automatically, and thus its reflectance $E_{\mathrm{dielectric}} \rightarrow 0$. We would retain specular_color $C$ as a non-physical tint of the reflection Fresnel factor.

This approach:

It is optional whether we want to have the specular_weight increase the Fresnel factor at the top end of the range (e.g. default at 0.5, and max out at 1, where the Fresnel is doubled, as the current specular_ior_level works) or not. It would be reasonable to just omit this, and have the weight default to 1, and only decrease the Fresnel.

Additionally, we propose to remove coat_ior_level, as it is functionally equivalent to coat_weight (the presence weight of the coat) for the purposes of modulating the coat reflection strength. Removing this also simplifies implementation of the coat lobe.

peterkutz commented 6 months ago

An specific side effect of the new proposal would be that it would eliminate any nonphysical mismatch of the Fresnel reflection and the corresponding Fresnel transmission. Any misalignment can be particularly noticeable when going from high IOR to low IOR due to the visible discontinuity where total internal reflection begins.