Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specular weight > 1 can cause energy gain in metals, and NaNs in dielectrics #224

Closed
portsmouth opened this issue Jul 18, 2024 · 5 comments

Comments

@portsmouth
Copy link
Contributor

portsmouth commented Jul 18, 2024

On testing we noticed that if specular_weight > 1 and the material is metallic, then there is energy gain, e.g.:

specular_weight 1 specular_weight 6
metaLwf_sw1 metaLwf_sw6

This happens because the specular_weight multiplies the metallic lobe as below:

image

We forgot to add a clamp to prevent the Fresnel factor exceeding 1 when the weight exceeds 1 though, which IMO is a mistake in the spec itself. We could either clamp the specular_weight before multiplying, or clamp each component of the final metallic Fresnel factor. The latter is closer to what we do for the dielectric case, so probably best.


Another issue we noted is that the formula below from the spec, for the dielectric Fresnel IOR ratio, produces inf if specular_weight is high, since $\epsilon=1$ then results (due to the clamp) which produces zero in the denominator (and this will later propagate into NaNs). This needs to be checked for and avoided, e.g. by clamping the denominator to be < 1.

image

This is not really an error in the spec (though arguably it is, since an infinite IOR doesn't make physical sense), but it's a rather easy mistake to make in implementing it (and thus generate NaNs in the render), so I suggest we point out the need to clamp explicitly in the spec.

NB, I think this bug is also present in the current MaterialX implementation.

@portsmouth portsmouth changed the title Specular weight > 1 doesn't make sense for metals Specular weight > 1 can cause energy gain in metals, and NaNs in dielectrics Jul 18, 2024
@portsmouth
Copy link
Contributor Author

portsmouth commented Jul 18, 2024

Also, we currently say the specular_weight full range is $(0, \infty)$ for dielectrics, but $[0,1]$ for metals, which doesn't make sense as there's only 1 parameter that has to have the same range for both cases. We should instead make it $(0, \infty)$ for both, and add the clamp to the metal description as noted above.

image

image

@portsmouth
Copy link
Contributor Author

Just to note, the implementation would be simpler if we just removed the facility to set specular_weight > 1, i.e. make the range be [0,1]. That seems like a reasonable simplification that is easier for UI and texturing. There is no loss of expressivity since specular_ior controls the base level reflectivity.

That also avoids the issue described here, i.e. having to insert awkward clamping logic to avoid unphysical energy gain.

@portsmouth
Copy link
Contributor Author

The suggestion above is implemented in #228

@virtualzavie
Copy link
Contributor

virtualzavie commented Sep 23, 2024

Here are a few observations on our side:

Specular weight for metal

I don't have any feedback on this part and I suspect (to be confirmed) it is not a use case for us.
Intuitively, I think it makes sense to permit the specular weight to be greater than 1, as this allows artists to tweak a metal appearance after the fact.

As for the solution proposed to avoid energy gain, I agree with the suggestion of clamping per channel. It could result in slightly unintuitive behaviour due to the hue shift, but as this happens when stretching the domain of the material, I think that's an acceptable tradeoff.

Specular weight for dielectrics

I am still gathering feedback and, more importantly, actual use cases, so I don't have a definitive answer yet. Here are some elements I've noted so far.

  • In general, artists don't have immediate examples of above 1 use cases (as opposed to examples of below 1 use cases, which they have plenty of). This suggest this is a rare use case.
  • That being said, artists prefer to have more freedom than less, and given the choice they will request to have the ability to increase the weight beyond 1.
  • One use case we have for specular weight above 1 is for scanned materials. My understanding is that it comes from two reasons:
    • A typical material scanning device won't measure IOR.
    • Assets are made to work on a wide range of platforms, and most assume a fixed IOR.
      Therefore the reflectivity is controlled with the specular weight only.
  • Technically, specular weight is another way to control IOR and therefore, any limitation in range could be worked around by using the IOR. However, artists tell me they associate IOR with the interior look, in particular refraction. In their mental model, IOR has nothing to do with reflection, and they find it counter intuitive to change it to adjust reflectivity.

From those observations, it looks like it might be harmless to clamp the weight, since scanned materials could always be processed.
What I am concerned about though, are the repercussions such a decision would have, especially on workflows with many artists making assets meant to be rendered together. In such workflows, artists typically have to follow conventions defined upfront. But if reflectivity has to be controlled with IOR, how would they define a sensible convention that doesn't prevent them from achieving the look of a particular asset later on?

@portsmouth
Copy link
Contributor Author

We decided to allow the specular weight > 1 case, and added the clamping logic to deal with it properly, in #238.

So this can be closed.

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

No branches or pull requests

2 participants