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

UsdPreviewSurface opacityThreshold implementation does not match the specification #2044

Open
ld-kerley opened this issue Sep 30, 2024 · 4 comments

Comments

@ld-kerley
Copy link
Contributor

ld-kerley commented Sep 30, 2024

The specification for UsdPreviewSurface states the following...

  • opacity - float - 1.0
    When opacity is 1.0 then the gprim is fully opaque, if it is smaller than 1.0 then the prim is translucent, when it is 0 the gprim is transparent. Note that even a fully transparent object still receives lighting as, for example, perfectly clear glass still has a specular response.
  • opacityThreshold - float - 0.0
    The opacityThreshold input is useful for creating geometric cut-outs based on the opacity input. A value of 0.0 indicates that no masking is applied to the opacity input, while a value greater than 0.0 indicates that rendering of the surface is limited to the areas where the opacity is greater or equal to that value. A classic use of opacityThreshold is to create a leaf from an opacity input texture, in that case the threshold determines the parts of the opacity texture that will be fully transparent and not receive lighting. Note that when opacityThreshold is greater than zero, the opacity values less than the opacityThreshold will not be rendered, and the opacity values greater than or equal to the opacityThreshold will be fully visible. Thus, the opacityThreshold serves as a switch for how the opacity input is interpreted; this “translucent or masked” behavior is common in engines and renderers, and makes the UsdPreviewSurface easier to interchange. It does imply, however, that it is not possible to faithfully recreate a glassy/translucent material that also provides an opacity-based mask… so no single-polygon glass leaves.

Currently the MaterialX UsdPreviewSurface implementation always blends the diffuse_bsdf and transmission_bsdf nodes based on the value of opacity.

    <mix name="transmission_mix" type="BSDF">
      <input name="fg" type="BSDF" nodename="diffuse_bsdf" />
      <input name="bg" type="BSDF" nodename="transmission_bsdf" />
      <input name="mix" type="float" interfacename="opacity" />
    </mix>

Which is incorrect. If opacityThreshold > 0, then the material should be in "masking" mode and only cut-out the surface, not blend through it.

I believe the fix would look something like this....

    <ifgreater name="transmission_mix_amount" type="float">
      <input name="value1" type="float" interfacename="opacityThreshold" />
      <input name="value2" type="float" value="0" />
      <input name="in1" type="float" value="1" />
      <input name="in2" type="float" interfacename="opacity" />
    </ifgreater>
    <mix name="transmission_mix" type="BSDF">
      <input name="fg" type="BSDF" nodename="diffuse_bsdf" />
      <input name="bg" type="BSDF" nodename="transmission_bsdf" />
      <input name="mix" type="float" nodename="transmission_mix_amount" />
    </mix>

@jstone-lucasfilm
Copy link
Member

This sounds like an important difference to resolve, thanks @ld-kerley, and I'm CC'ing @klucknav for her expertise in this area. If there's broad agreement that the MaterialX graph needs to change, then we can make this update in a pull request.

@ld-kerley
Copy link
Contributor Author

ld-kerley commented Oct 1, 2024

I put together a quick example - attached in the zip file.

In the screen grab below.

  • Left column is UsdPreviewSurface
  • Right column is MaterialX version of UsdPreviewSurface
  • Top row has opacityThreshold set to 0.1
  • Bottom row has opacityThreshold set to 0

Note some differences may come from differences in colorspace management, but we can see the change in blend/cutout behavior between the cases.

usdview_screenshot

@jstone-lucasfilm
Copy link
Member

I'll defer to @klucknav on which behavior is canonical for UsdPreviewSurface, and as one additional reference point, we previously collaborated with Karen and Spiff on an update to the opacity threshold behavior in the MaterialX graph for UsdPreviewSurface:

#1186

At the time, we believed this brought the MaterialX graph for UsdPreviewSurface into alignment with the specification, but it's very possible that we missed an edge case.

@ld-kerley
Copy link
Contributor Author

Looks like my example zip file didn't get attached...

leaf_example.zip

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