-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Conversation
Related tests in the asset generator here: I think we might want to explain exactly what "mirrored geometry" means. I don't see any negative scales in the glTF file for this PR, so I'm assuming the geometry was mirrored in the DCC tool? |
Great test model, thanks! For my own ignorance, what motivation would an artist usually have in supplying tangents? Is this done because they're not confident the engine will calculate tangents correctly? Or do supplied tangents improve visual quality... enable UV mirroring... something else? |
I can think of a few reasons for supplying tangents:
|
So I created this model after reading some discussion of a problem with DamagedHelmet (somewhere... I think in KhronosGroup/glTF-Sample-Viewer#65). The helmet model has two halves, and one side is a mirror of the other side (in the DCC tool, not with a scale command). The corresponding UV maps then have only half of the pixels they would otherwise have, since the UV atlas need only cover one side of the helmet. But there's a problem: On the "mirrored" side of the helmet, all of the normal-mapped indentations are portrayed as bumps, and bumps as indentations. It was suggested this is because the current helmet model does not supply tangent vectors, and relies on the engine to generate them. The generated tangents don't take the mirroring into account, and the +/- sense of the normal map gets flipped. Thus, a revelation: Supplying tangent vectors can actually save space in the form of texturemap data that need not be repeated for mirrored geometry. So I made this model to test the theory, that simply taking the old NormalTangentTest into Blender, creating mirror copies of the normal-mapped quads, would result in geometry that didn't auto-generate tangents correctly, and that Blender would supply the correct tangents. This is quickly and easily confirmed with this model (by removing the reference to the tangents in BabylonJS, or just by viewing in ThreeJS where tangents are always auto-generated and supplied tangents are ignored). It also uncovered a number of issues in Cesium, which wasn't ingesting supplied tangents correctly at all. In any case, when exporting normal-mapped geometry that may have been mirrored, it would appear that supplying tangents is the safest thing to do. |
Think of it this way: For mirrored geometry, it's as if the normal map calculation had taken place on the back faces of all the polygons, instead of the front faces. |
I think the reason why removing the tangents don't work in three or Babylon is because neither implementation compute tangents use MikkTSpace algorithms as per spec. Assuming using a proper algorithm will result in correct tangents (even for mirrored geometry), I don't see why supplying tangents will result in a smaller download since the texturemap data will not need to be repeated. |
I don't know the details of MikkTSpace calculation, but there's a more fundamental problem here, and I'm having trouble describing it. Please bear with me as I make another attempt. In the "normal" columns above, tangents are calculated the normal way, and work as expected whether you use the supplied tangents or you calculate them in the fragment shader. In the "mirror" columns above, two steps were taken in Blender:
By the end of step 2, a single-sided material will show this polygon only from the front and cull it from the back, and the vertex normals face front too. The only remaining change here is the mapping of the UVs. Here's a screenshot of what happened to the normal map image as a result of UV mirroring: And there it is. The actual image of the normal map itself has been mirrored, first vertically, then horizontally. No matter how good your math is, you can't "know" that this has happened, unless you have the tangent vectors supplied. There are no clues to be found in the winding order or normal vector. If you don't know these images apply to the back face, you're going to get inverted normals, and it will look like the back faces. The supplied tangent vectors are required to fix this. |
I think this problem is exclusive to when a normal map is "baked" using forwards geometry, and then applied to a mirrored-and-flipped version of that same geometry. |
I see what you mean now. I wonder how often this kind of thing happens. I'll ask tech art. |
Even if it turns out to be not all that common, I'll postulate that this is still a valuable addition to our test model suite, because:
|
Yeah, I'm not arguing that at all. I'm just curious. |
Thanks for the detailed explanation, I'm also a +1 for including the sample, just trying to get a better idea of if/when three.js should consider implementing. |
I tried this model with gltf-test. The current status is as follows. https://github.com/cx20/gltf-test#agi-sample-models (It is not a complete test because some WebGL Engine can not display the environment map. I need to check how to use the environment map for each WebGL engine, but it seems that it will take time.) |
Thanks for your awesome tests @cx20. Cesium will be fixed with the 1.44 release on April 2nd. CesiumGS/cesium#6302 |
This issue can be quickly fixed in the calculation of the normal map tangent space because it is possible to detected mirrored faces by comparing the specified normal with the tangent space normal. Just update Three.JS's normalmap_pars_fragments.glsl with this code and it probably will be fixed - it is a four line fix I think:
|
The existing Normal-Tangent test model tests an engine's ability to automatically generate the correct tangent vectors given only a set of normal vectors and a tangent-space normal map.
This new model tests an engine's ability to use the supplied tangent vectors, and in particular includes tests for when geometry has been mirrored. Mirrored geometry relies on the supplied tangent vectors to indicate the correct direction, and if they are replaced with auto-generated vectors there will be a visible difference.
The README files for both NormalTangentTest and NormalTangentMirrorTest have been overhauled with instructions on how to perform the test and read the test results, along with screenshots of what the tests look like when they pass, and what they look like in the most common failure patterns that have been observed with these models.