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

Transparent model does not render on some machines #26167

Open
bennlich opened this issue May 29, 2023 · 11 comments
Open

Transparent model does not render on some machines #26167

bennlich opened this issue May 29, 2023 · 11 comments

Comments

@bennlich
Copy link

Description

I have a GLB of some transparent cloud shapes. On some computers (Intel macbook), they render fine:

Screen Shot 2023-05-29 at 1 25 11 PM

On other devices (Macbook w/ M2 chip, debian laptop, 10th gen ipad), they do not seem to render at all:

Screenshot 2023-05-30 at 1 52 50 AM

Reproduction steps

  1. Download the GLB https://nac-prod.sfo2.cdn.digitaloceanspaces.com/1607/clouds-l_nvBBMv.glb
  2. Plop it into mccurdy's wonderful viewer: https://gltf-viewer.donmccurdy.com/

Code

N/A

Live example

See steps above

Screenshots

No response

Version

r151

Device

Desktop, Mobile

Browser

Chrome, Safari

OS

MacOS, Linux, iOS

@donmccurdy
Copy link
Collaborator

Notable material properties:

  • alphaMode: "BLEND"
  • alpha: 0.44
  • transmission: 0.14
  • IOR: 0.0
  • roughness: 0.5
  • metalness: 0
  • baseColor: #FFFFFF

A non-zero IOR is probably intended here, perhaps between 1.0 and 1.33. Based on the MeshPhysicalMaterial documentation, I'm not sure if three.js supports .ior = 0? glTF does allow it, and it can be helpful in converting spec/gloss to metal/rough materials, though very high IOR values will work just as well. That the material disappears on certain devices and not others is a surprise to me....

@gkjohnson
Copy link
Collaborator

gkjohnson commented May 30, 2023

I'm not sure if three.js supports .ior = 0? glTF does allow it...

What is ior = 0 supposed to mean? With refractive indices it's common to work with ratios between the external and inner medium light is being transmitted through. So you'll have to do things like 1 / ior in some cases - such as here:

vec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );

I wouldn't be surprised if this gives undefined or inconsistent results. I do see in the spec that the valid value ranges are >= 1.0 or 0 explicitly. It's possible our shader needs a special case to handle a 0 ior - though it's not immediately clear to me from the spec what the behavior is supposed to be.

@donmccurdy
Copy link
Collaborator

From the spec —

Valid values for ior are numbers greater than or equal to 1. In addition, a value of 0 is allowed. This value gives full weight to layer, i.e., the Fresnel term evaluates to 1 independent of the view or light direction. It is useful in combination with KHR_materials_specular to seamlessly support the specular-glossiness workflow.

The Fresnel term also evaluates to 1 for very large IOR values. However, KHR_materials_specular is not involved here. I'm not sure what use ior=0 has within a transmissive material.

@RemusMar
Copy link
Contributor

Valid values for ior are numbers greater than or equal to 1. In addition, a value of 0 is allowed.

Those specs are quite obfuscated (I don't want to say bad designed).
That 0 should not be there.

@mrdoob
Copy link
Owner

mrdoob commented May 30, 2023

@elalish Do you know the reasoning behind that 0?

@bennlich
Copy link
Author

I re-exported the model with an IOR of 1 and verified that it renders on one of the machines where it was previously not rendering.

@RemusMar
Copy link
Contributor

I re-exported the model with an IOR of 1 and verified that it renders on one of the machines where it was previously not rendering.

That's because ThreeJS does not support ior = 0
And honestly, mixing a range with a flag in the GLTF spec was a bad idea.

@donmccurdy
Copy link
Collaborator

That glTF allows ior = 0 does not mean MeshPhysicalMaterial must do so, we can map it to whatever parameterization we find appropriate for our user-facing Material API, or not. But we should try to understand the purpose of the value in the specification — it has an important role in some contexts. I'm not sure whether transmissive materials are one of those contexts.

@WestLangley
Copy link
Collaborator

WestLangley commented May 30, 2023

FWIW

Valid values for ior are numbers greater than or equal to 1. In addition, a value of 0 is allowed. This value gives full weight to layer, i.e., the Fresnel term evaluates to 1 independent of the view or light direction. It is useful in combination with KHR_materials_specular to seamlessly support the specular-glossiness workflow.

It also says,

This extension must not be used on a material that also uses KHR_materials_pbrSpecularGlossiness.

ref: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_ior

@donmccurdy
Copy link
Collaborator

The implication above is that ior=0 or ior=Infinity can be used to losslessly convert from the spec/gloss PBR workflow (KHR_materials_pbrSpecularGlossiness) to a standard metal/rough PBR workflow. The conversion tools recommended in #24950 assign ior=1000. Longer discussion in KhronosGroup/glTF#1719 (comment). None of those concerns appear relevant to transmissive transparency, however.

@donmccurdy
Copy link
Collaborator

donmccurdy commented May 31, 2023

As a test, I've modified the TransmissionRoughnessTest sample to include ior=0 and ior=1000. The last row, unlabeled, is opaque with default IOR.

TransmissionIORTest.glb.zip

engine screenshot
three three
babylon babylon
khronos khronos
playcanvas playcanvas

If we don't want to support ior=0 as an input to MeshPhysicalMaterial (which is fine with me), then perhaps we should just have GLTFLoader map ior=0 to ior=[large value] instead. The effect is the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants