AcademySoftwareFoundation / OpenPBR

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

Add a discussion/solution of the coat "spurious TIR" issue #166

Closed portsmouth closed 2 months ago

portsmouth commented 5 months ago

This addresses the points raised in https://github.com/AcademySoftwareFoundation/OpenPBR/issues/142.

I made it a sub-section of the Coat section, as it relates to accounting for the presence of the coat in the implementation of the dielectric/specular BSDF, but it could possibly go in the earlier Dielectric base section with a forward reference.

image

portsmouth commented 4 months ago

An image of the artifact and the fix probably makes sense as well, to give some intuition.

portsmouth commented 3 months ago

An image of the artifact and the fix probably makes sense as well, to give some intuition.

That can be done as part of a PR with an overhaul of the images.

peterkutz commented 3 months ago

This seems like a good place to put this discussion to me, since it's not very relevant before the coat is introduced.

peterkutz commented 3 months ago

This is a nice addition and an interesting technique. However, to me doing these calculations at the microfacet level seems like overkill. I believe there's a simpler solution.

If I understand correctly, you are modifying the cosine at the microfacet level in order to squeeze the set of incident directions into a smaller range of angles, which avoids angles that result in TIR.

Instead of modifying the angles to squeeze them into the part of the Fresnel curve without TIR, we could equivalently modify the Fresnel curve to expand the part without TIR into the full range of angles.

Luckily, inverting an IOR results in the original Fresnel curve being squeezed or stretched into a smaller or larger set of angles, which respectively introduces or eliminates TIR. So we can achieve the desired outcome by inverting the relative IOR of the microfacet instead of modifying the cosine.

We can then take that one step further. Since all microfacets share the same relative IOR (unlike the cosine, which is different for each microfacet), we can simply modify the relative IOR of the whole base lobe, eliminating the need to modify the lobe internals at all.

This also avoids the costly second Fresnel evaluation for partial coats. For partial coats, we can simply blend the base IOR and the adjusted relative IOR (or the corresponding F0 values) and provide that to the base specular lobe.

The implementation is straightforward and efficient: when $n_c > nb$, simply set $\eta\mathrm{bc}$ to $n_c/n_b$ (instead of $n_b/n_c$).

peterkutz commented 3 months ago

I have one additional concern with the proposed approach, which is that modifying the cosine would also have the side effect of changing the metallic reflection from the microfacets as well (assuming that the dielectric and metal components share the same microfacet distribution). In particular, it would eliminate all grazing angles and thus eliminate the F82-tint edge color. This might be more physically correct for smooth base surfaces but it doesn't make sense for rough base surfaces where the microfacets could really be struck from any angle regardless of the coat refraction. Was this intentional?

jstone-lucasfilm commented 3 months ago

I'm open to the simple inversion approach proposed by @peterkutz, and I believe this is similar to the approach taken in Adobe Standard Material. What are your thoughts, @portsmouth?

peterkutz commented 3 months ago

I have implemented the different options in Mathematica to verify that they work as expected.

The plots below show a dielectric configuration that exhibits TIR, the approach of inverting the relative IOR, and the approach of transforming the cosine. This illustrates that the IOR inversion and cosine transformation approaches have exactly the same effect.

(I'd be happy to run more tests or post the Mathematica notebook if useful.)

OriginalSituationWithTIR InvertedIORApproach TransformedCosineApproach

portsmouth commented 3 months ago

I think there may be a slight confusion about formula I proposed. In my proposal I had:

$$ \mu_c^2 = 1 - (1 - \mui^2) / \eta^2\mathrm{ca} \ . $$

Which simply gives the angle of the ray inside the coat, after it is refracted from the exterior ambient medium into the coat (assuming a totally smooth coat). Note that it is $\eta\mathrm{ca}$ that appears here, not $\eta\mathrm{bc}$ (as this is the refraction at the coat/ambient boundary). I then required that this angle is the one we use in the microfacet Fresnel formula for the base (specular) lobe:

$$ F(\muc, \eta\mathrm{bc}) $$

where in this Fresnel factor, $\eta_\mathrm{bc}$ is used since this ray is reflecting off the coat/base boundary. Since physically, if the coat was smooth, that is the actual angle of incidence at the coat/base boundary. (The coat is not generally smooth, so this is approximate, but we avoid the TIR artifact at least).


In your formula, I take it you are replacing that Fresnel factor with:

$$ F(\mui, \eta\mathrm{cb}) $$

i.e. just inverting the IOR ratio at the coat/base boundary (and supplying the unmodified incident angle from the exterior to the coat). The plots you show are showing (I take it) that this equals a Fresnel factor with the inverse IOR ratio:

$$ F(\mu^\primei, \eta\mathrm{bc}) = F(\mui, \eta\mathrm{cb}) $$

(That follows basically from time-reversal invariance I think, i.e. the Fresnel reflection factor for A -> B is the same as that for B -> A, if you imagine the rays reversing direction, which is non-obvious but true e.g. Stokes relations). But I think the $\mu^\prime_i$ that satisfies the equation above is the direction of the $\mu_i$ ray if refracted at the coat/base boundary, not $\mu_c$ which is what we wanted to match.

So I see that your approach avoids the TIR, since it artificially swaps the IOR of coat and base so that the coat IOR is always lower. But I don't think that is faithful to the physics, as this doesn't correspond to any actual Fresnel factor in the true light transport, even in the smooth limit. We might as well just forbid the coat IOR to be higher than the base, rather than swap them internally.

Of course, I could be misunderstanding or missing something in my thinking about your proposal. (Mathematica notebook would indeed be helpful to verify I understand your plots).


I have one additional concern with the proposed approach, which is that modifying the cosine would also have the side effect of changing the metallic reflection from the microfacets as well (assuming that the dielectric and metal components share the same microfacet distribution). In particular, it would eliminate all grazing angles and thus eliminate the F82-tint edge color. This might be more physically correct for smooth base surfaces but it doesn't make sense for rough base surfaces where the microfacets could really be struck from any angle regardless of the coat refraction. Was this intentional?

True, though this seems hard to avoid without doing a full Monte Carlo simulation of the scattering between the rough interfaces (or something like the Weidlich and Wilkie model, which is essentially a stochastic MC simulation layer by layer). If there is a coat over a metal, won't the coat Fresnel generally mask the F82 tint anyway? It could be useful to study some renders to see if there really is a significant artifact introduced by my form of the TIR fix.

peterkutz commented 3 months ago

@portsmouth

I think there may be a slight confusion about formula I proposed. In my proposal I had: ... Which simply gives the angle of the ray inside the coat, after it is refracted from the exterior ambient medium into the coat (assuming a totally smooth coat). ... I then required that this angle is the one we use in the microfacet Fresnel formula for the base (specular) lobe: $F(\muc, \eta{bc})$

Right, that is what I understood from the formulas, thanks for clarifying. However that description doesn't seem to fully align with your proposed text in the spec:

... assume, within the base dielectric BRDF microfacet model, that each microfacet is coated with a smooth clear-coat with matching micronormal ... Then if the coat is present, the angle cosine $\mu_c$ to the base micronormal is given by refraction of the incident angle cosine $\mu_i$ as follows:

Specifically, "the angle of the ray inside the coat" is not the same as"the angle cosine $\mu_c$ to the base micronormal". The former is the refracted "V dot N" whereas the latter is "V dot H", where "H" is the half vector corresponding to the microfacet normal calculated with "normalize(V dot L)".

The formula $F(\muc, \eta{bc})$ also suggests that the refracted "V N" is being passed in to the Fresnel function directly, but the Fresnel function is applied to microfacets so it should accept "V H" as input.

Also, the spec also says that "each microfacet is coated with a smooth clear-coat with matching micronormal", but that is not the real coat since the real coat does not have a matching micronormal. So that statement does not align with the statement that the cosine transformation "simply gives the angle of the ray inside the coat, after it is refracted from the exterior ambient medium into the coat".

If you are in fact suggesting to use angle of the ray inside the real coat at a global level, then that also raises questions, such as whether this angle refers to the view direction, the light direction, or both.

Let me know if I'm missing something. I'll follow up with another reply about my proposal, which is a simple modification to the lobe inputs analogous to the coat roughening, produces similar results, and has already been used in production.

peterkutz commented 3 months ago

But I think the that satisfies the equation above is the direction of the ray if refracted at the coat/base boundary, not which is what we wanted to match.

Good point. After reading your replies and looking at the problem more closely, I see that while my solution produces a plausible result, it does not produce the correct results in general. Instead, it produces a base specular reflection that is slightly too intense (although in practice this might actually help to make up for the energy that's missing due to ignoring coat internal reflections).

Instead of inverting the IOR, I wonder if there would be a way to transform the IOR to produce the exact result or at least a more accurate result. Since you're good at this type of mathematical problem, I wonder if you might have an idea of how to do this.

At a high level, I still prefer the approach of modifying the IOR for a few reasons:

Even if the IOR inversion technique can't easily be made more accurate, I would propose noting it as an alternative solution for implementers that find the cosine-modification technique too invasive or complex.

Below are a couple relevant attachments.

The Mathematica code (in text form because .nb files can't be attached) used to generate the above plots (which are relevant but not fully representative of the actual situation in question):

FresnelComparisonsForSpuriousTIRIssue.txt

The test renders I did for ASM validating the plausibility and reasonable accuracy of the IOR inversion technique (from the ASM technical document):

ASMSolutionForSpuriousTIR
peterkutz commented 3 months ago

I have also created some slides to intuitively illustrate how the IOR inversion technique works as well as its limitations. (It's best to flip between the pages like a slideshow to more easily see what changes from slide to slide.)

PeterProposedFixForSpuriousTIR.pdf

portsmouth commented 2 months ago

@peterkutz Regarding your critique above, what I meant (but didn't write up correctly), is that the diagram below is supposed to be in the local space of the base microsurface, and in the approximation that the over-lying coat microsurface has matching micronormal. I realize this is not strictly correct (i.e. the coat micronormal of course may differ -- though we don't know what it is if we're evaluating the base BSDF independently from the coat), but for the purposes of the Fresnel calculation it's an (imperfect) approximation that doesn't introduce any major artifact but fixes the major TIR artifact.

So the $\mu_i$ in this picture is $\omega_i \cdot m$ where $m$ is the shared micronormal. From that you can compute $\mu_c$ and the Fresnel factor $F(\muc, \eta\mathrm{bc})$, which avoids the TIR.

image

I don't intuitively see how inverting the base IOR (or otherwise changing it) is a better approximation, since this avoids the TIR by essentially fudging the IORs in the calculation to make the TIR impossible. Though it is simpler to implement I admit. Perhaps we can compromise by you adding a brief explanation of the TIR inversion trick as an additional suggestion?

(And I can also fix up my proposal to make the assumptions about the microsurface more clear).

portsmouth commented 2 months ago

Instead of modifying the angles to squeeze them into the part of the Fresnel curve without TIR, we could equivalently modify the Fresnel curve to expand the part without TIR into the full range of angles. We can then take that one step further. Since all microfacets share the same relative IOR (unlike the cosine, which is different for each microfacet), we can simply modify the relative IOR of the whole base lobe, eliminating the need to modify the lobe internals at all. This also avoids the costly second Fresnel evaluation for partial coats. For partial coats, we can simply blend the base IOR and the adjusted relative IOR (or the corresponding F0 values) and provide that to the base specular lobe. The implementation is straightforward and efficient: when nc>nb, simply set ηbc to nc/nb (instead of nb/nc).

To be fair, this all sounds highly plausible and could be more efficient than what I propose. So perhaps what we can do is refactor my discussion to merely state the source of the problem (the bending of the ray, show the existing diagram etc.), but state your scheme as our suggestion for an approximate but efficient/practical solution. Do you mind to attempt to draft that?

We should probably also say that the Weidlich-Wilkie approach is the more correct way to do this, i.e. work through the layers in sequence doing stochastic Monte-Carlo samples of the micronormals etc. Which e.g. PBRT actually does.

peterkutz commented 2 months ago

Thanks for the clarifications @portsmouth . It makes more sense and if I understand correctly it is just trying to approximate the actual physics where the light is reaching the base surface from a limited cone of directions. It seems fine to include (the clarified version of) this suggestion in the spec.

fudging the IORs ... simpler to implement ... TIR inversion trick as an additional suggestion

I think that might be good to include the IOR modification as an additional suggestion since they are both approximations anyway (compared to something like the Weidlich-Wilkie approach) and since the IOR modification might be easier to implement and better than nothing.

Do you mind to attempt to draft that?

Sure, I wouldn't mind drafting something, although I won't have availability to do that until after the 1.0 release.

Does anything special need to be done for light samples with your approach?

portsmouth commented 2 months ago

Does anything special need to be done for light samples with your approach?

Not that I'm aware.

portsmouth commented 2 months ago

In 8a43437953eb494754b9b0d2f12f6a6500b7f671 i've updated the TIR section to:

image

image

portsmouth commented 2 months ago

I think this is good to merge now, pending approval from Julien and/or Peter.