-
Notifications
You must be signed in to change notification settings - Fork 18
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
Coat roughening convolution formula #172
Coat roughening convolution formula #172
Conversation
To be more clear, we should cross reference this formula in the dielectric and metal sections, to remind the reader to apply the roughening if the coat is present. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The phenomenon is already implemented in the MaterialX implementation using the standard surface formula, so describing it in the spec is important. We need to validate the new proposed formula and add a MaterialX implementation.
Using If that discontinuity bothers you, the following formula is almost the same but is smooth everywhere:
I think the current wording in the spec is totally fine, no need to change it. Just pointing out an alternative that would be very close. Depending on where we end up with respect to anisotropy for coat vs base, we may need to generalize the formula to operate on the 2x2 matrix of alpha values (haven't thought about exactly what the math should be, but its probably a similar kind of formula that would come back to @portsmouth's one in the isotropic case). |
Nice suggestion and visualization @fpsunflower! It's nice that your modified formula produces very similar values across most of the domain while avoiding the discontinuity. It also meets all of the other requirements such as producing an output at least as large as the inputs. In case it's easier to read or reason about, here's a different way of writing it:
|
Thanks Chris, that's a nice formula. I plotted it here (where green is mine, dashed green is yours, blue is Standard Surface, red is max): https://www.desmos.com/calculator/svkp9j7kwc Your formula is very close to the original one, unless the base roughness is quite large. I think it would be fine to re-word the section to say, the convolution would give my formula, but we suggest your modification (or Peter's form of it) to ensure the curve is close to that but smooth between the [0,1] endpoints. |
That has a somewhat nice similarity to the Standard Surface formula, which is the same but just removing the fourth powers: |
I posted a possible sketch of the math for that on Slack:
Though I think that it is too much math for the spec. Ideally someone should investigate whether a scheme like that works, and verify with some Monte Carlo simulations. (Then we could just reference that). Incidentally, the assumption that the NDF of the observed base lobe seen through a rough coat is given by convolving the NDFs of coat and base, is just a guess (loosely based on the Belcour paper where he does similar approximations with the variance of lobes, to account for layering, which possibly we should reference). The reality will obviously be more complex (the full BRDF of coat-on-base involving accounting for all possible scattering paths within the coat, and a term with the two NDFs being integrated together is just one lowest-order part of that). Technically OpenPBR doesn't say this convolution formula must be used though, it's just a suggestion (the ground truth would be whatever happens in the full light transport). |
Actually the NDF of the coat should presumably count more highly in the mix, since in the lowest-order path the ray has to pass through the coat boundary twice, and bounces only once on the base surface.. So a more realistic formula would involve doubling the variance contribution of the coat, i.e. Then the base roughness saturates to 1 at: e.g. a smooth base becomes maximally rough at Below green is with the coat counting twice, and red the original formula. If you do this, I'm not sure it makes sense to try to smoothen out the discontinuity. https://www.desmos.com/calculator/qizje7v8bx Possibly you could still regard Chris's formula (dashed red) as a reasonable, smooth bounded approximation of that as well. This is all loose enough that perhaps it doesn't matter exactly what formula we recommend, if it has nice visual behavior reasonably similar to the expected ground truth (and as a bonus has some kind of theoretical rationalization). It would probably help to see some renders with varying base and coat roughness, and the effect of the formula with the clamp in comparison to the smooth formula. (I'm expecting barely perceptible difference, but will see). |
Suggest smooth approximation.
Re-wording in 6c66e3b |
The MaterialX implementation of this is needed. (Just need to decide which formula..). |
… into coat_roughening
I added a simple MaterialX implementation of the more realistic coat roughening formula as in Equation 55 from the spec shown above, replacing the old Standard Surface one. The clamped version seems fine to use, and more principled than the approximate version of Equation 56 (which I removed from the spec text as well). |
# Conflicts: # index.html
# Conflicts: # index.html
… into coat_roughening # Conflicts: # index.html
Ready to merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
||
### Roughening | ||
|
||
If the coat is rough, the microfacet BSDF lobes of the underlying base substrate (metal and dielectric) are also effectively roughened. If this is not otherwise accounted for by the light transport, it can instead be reasonably approximated by directly altering the NDF of the base BSDFs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
# Conflicts: # index.html # reference/open_pbr_surface.mtlx
@virtualzavie suggested offline that this could benefit from a more detailed discussion of the derivation of the suggested formula, which I agree with. But I'd suggest for 1.0 we just get the existing PR in with the formula and the implementation, as adding a more detailed description is presumably allowable after "code complete". |
This change looks good to me, @portsmouth, and I'm fine to merge this work once we've validated rendering of the updated implementation in MaterialX 1.39. |
This changelist fixes a minor typo in the new implementation, updating a connection from "interfacename" to "nodename". Signed-off-by: Jonathan Stone <jstone@lucasfilm.com>
This changelist updates a connection from "nodename" to "interfacename" for correctness. Signed-off-by: Jonathan Stone <jstone@lucasfilm.com>
@portsmouth I addressed two very minor typos in the reference implementation, and I'm now getting successful renders of coated materials in the MaterialX Viewer: One unusual behavior that I should call out, though, is that neither If I set Could this be a bug in our reference implementation, or is this behavior actually expected given the latest OpenPBR specification? |
Thanks for the typo fixes. If I load the "car-paint" material, and dial the coat anisotropy, then indeed the anisotropy doesn't seem to show up (i.e. the sun reflection doesn't smear). But this just seems to be a case of what Zap was complaining about, i.e. when the coat roughness is zero, coat anisotropy doesn't do anything.. (i.e. the roughness stays at zero, in both directions). That is by design, yes. Also... in this material, the specular and coat IORs are equal (!). So the specular lobe is not showing up at all. So that accounts for the specular anisotropy not showing up either. If you make the roughnesses non-zero and the IORs differ, then you will see the effect of the anisotropy in both lobes. If you think that's unintuitive, we can discuss in the meeting (but it's the behavior of the spec, correctly implemented, I think). So anyway, I think the PR is good to go, as we've verified it now in MaterialX. |
Got it, and I'm fine to merge this latest pull request, as the specification and reference implementation are aligned. It's arguable that we can do a better job of making these behaviors intuitive, e.g. making sure there's always a visual impact associated with moving the anisotropy slider, but I'll leave that judgement to artists with more production experience. |
Here is an example of the coat roughening behaving correctly (IMO), including anisotropy. The coat and spec IORs are different. The coat is slightly rougher than the spec. Both are highly anisotropic. Without the coat (just the spec lobe, tight stretched highlight): With the coat (highlight of coat and spec superimposed, coat highlight much broader): This does show one defect of the roughening formula, in that the anisotropy of the base lobe is not affected. In fact, an isotropic rough coat should cause the base lobe to become less anisotropic. But we opted to neglect such anisotropy effects for now. (Later we could try to improve that though, for sure). |
e7ec2c7
into
AcademySoftwareFoundation:main
Another thing to note, is that the weird brightening around the edge of the lower image above, is the "spurious TIR artifact" -- which shows up here because the coat IOR is higher than the spec. So the spec lobe "thinks" that the rays are incoming from a higher IOR, so TIR occurs. Which is false, as physically the rays should actually pass through the coat and bend, eliminating that TIR. The PR #166 proposes a discussion of this with a suggested practical solution. I will attempt to fix this up in time for the meeting, to incorporate Peter's suggestions. |
Essentially, an improved version of the Standard Surface roughening formula. We need to suggest some approximation, as implementations need to account for this somehow. As discussed on Slack, thinking about the roughening as a convolution suggests an "as simple as possible" physically-based formula for the effect. I assume this is closer to the ground truth than the ad-hoc Standard-Surface formula, but verifying that would require more work.
See the interactive graphs here for the difference between the Standard Surface (green) and convolution (blue) formulas: https://www.desmos.com/calculator/tvvzlmjqin