-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
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
Inconsistent behaviour when non-existing UV indices are accessed #27552
Comments
Personally I'm grateful for the glTF specification's strictness in this area. There are already a handful of cases where we need to 'clone' one glTF material into multiple three.js materials, and those cases have been recurring sources of challenges and bugs. I'd be sad to see the glTF specification encourage more of that, and I'm not sure I agree that the popular use of glTF for interchange requires these changes, or justifies the added cost on runtimes. By way of example, see: This represents a number of long-standing issues in both React Three Fiber and Threlte, for which the only solution I've come up with is to pre-process the glTF files and ensure that materials are duplicated in the source glTF file for every case where THREE.GLTFLoader might otherwise need to clone that material. All of that said ... I don't necessarily feel strongly about what three.js should do given |
While I personally think a runtime should always try to render something, I understand that may not be in scope for three.js. That's why I labeled the issue with "inconsistent", not "broken/wrong" – I'm not sure why having some objects that have that UV attribute and some that don't have it results in a working scene, while when all objects don't have it it breaks. Requiring duplication in the source glTF is very much the opposite of interchangeability :) may be one more case where a more strict spec separation between "using glTF for pipelines" (where names can and should occur multiple times, materials can be reused, ...) and "using glTF for strict GPU-friendly delivery" (where names may need to be unique and in extreme cases every object has a unique material) would have been good... I think: we want three.js to fall back to an existing UV set or to 00, to align with how other renderers handle missing UV attributes. |
To recap: That is not true for
No sanitization happens in the renderer. That The thing that should be fixed is to ensure } else if ( materialProperties.vertexUv1s !== vertexUv1s ) {
needsProgramChange = true;
} else if ( materialProperties.vertexUv2s !== vertexUv2s ) {
needsProgramChange = true;
} else if ( materialProperties.vertexUv3s !== vertexUv3s ) {
needsProgramChange = true;
} However, this check is too strict since difference sets of uv attributes do not necessarily require a different shader. The question is whether textures actually use specific uv attributes which are not present in all geometries. Testing for this is complicated and we have to do it for all render items each frame. For now, I would prefer to not add any changes to the renderer. As long as assets are defined in a glTF compliant way, everything should work as expected.
TBH, this is a bad pattern and should be reported as a bug at the respective glTF exporter. What is the purpose of having glTF validation if exporters do not honor it? Sorry, but not even optimization purposes justify the production of invalid assets. This is just causing issues everywhere in the ecosystem. |
I generally agree but if enough users/renderers do it, it should also bubble back up to Khronos to point out flaws in the spec, which I did (referenced in the original post). The runtime behaviour in three.js is the outlier right now. |
@Mugen87 I don't think there was a real resolution here... I also want to note that this will become more common with wider MaterialX / NodeMaterial usage – somehow "this node needs UV2 but it doesn't exist" should be handled or material interchange won't work. MaterialX has fallbacks for missing attributes. |
What is that fallback mechanism? In terms of the glTF proposal — I'm really not sure about falling back to While perhaps Blender can load files with missing UVs, it does (to my understanding) still require duplicating materials to assign distinct UV channels to different textures arbitrarily. I'm not really on board with characterizing three.js as an "outlier" here — different implementations fail in different ways, which is a strong argument for why glTF prohibits the case. |
If we do want to change this behavior in three.js, I think the two options would be —
In both cases, I worry that we'd be hiding user error more often than providing a useful behavior. 😕 |
Description
Currently, when a material says "I need UV2" and the geometry doesn't have it, rendering just stops with shader errors. This can happen manually or when loading glTF files that are strictly speaking invalid (validator complains) but are nonetheless produced by applications because it's better for interoperability to have one material than having to duplicate it.
I did a few tests with various viewers and the behaviour is slighty different, but the files attached below "mostly work" elsewhere: KhronosGroup/glTF#2360
The behaviour is inconsistent right now, sometimes accessing missing UV index data works (UVMismatch_UV1 below) and sometimes it fails (UVMismatch_UV2 below). Maybe some place in the code already sanitizes specifically UV1, but not UV2?
Reproduction steps
Load this file in https://threejs.org/editor or https://modelviewer.dev/editor:
UVMismatch_UV2.glb.zip
Note shader errors in the console (UV2 is accessed, both objects don't have UV2)
Load this alternative file:
UVMismatch_UV1.glb.zip
Note file renders for some reason (UV1 is accessed, one object doesn't have UV1)
This file also breaks with just UV1 missing: LOUVRES.005.glb.zip
Version
r161
The text was updated successfully, but these errors were encountered: