Normal texture flickers

Hi,

When uploading this small low-res tree GLB model with a normal map (“normalTexture”), the result is flickering:

I choose “3D Model (convert to glTF)” and disable both “Optimize for rendering” and “Draco compression”. My imported asset ID is 2701504.

The normal map is there to resemble the high-res version from afar. Its texture mapping kind of works but flickers like crazy. Anyone with an idea of what might be wrong?

Regards,
Andreas

This is not a problem with CesiumJS or Cesium ion, but with the model itself.

Looking at the data from the POSITION accessor:

[(  -8.56224,   11.66443,   12.01517), 
 (   9.24635,   11.66443,   12.01517), 
 (   9.24635,  -12.25911,   12.01517), 
 (  -8.56224,   11.66443,   12.01517), 
 (   9.24635,  -12.25911,   12.01517), 
 (  -8.56224,  -12.25911,   12.01517), 
 (  -8.56224,  -12.25911,   12.01517), 
 (   9.24635,  -12.25911,   12.01517), 
 (   9.24635,   11.66443,   12.01517), 
 (  -8.56224,  -12.25911,   12.01517), 
 (   9.24635,   11.66443,   12.01517), 
 (  -8.56224,   11.66443,   12.01517), 
 (   0.00000,   11.66443,    2.57523), 
 (   0.00000,   11.66443,   20.86043), 
 (   0.00000,  -12.25911,   20.86043), 
 (   0.00000,   11.66443,    2.57523), 
 (   0.00000,  -12.25911,   20.86043), 
 (   0.00000,  -12.25911,    2.57523), 
 (   0.00000,  -12.25911,    2.57523), 
 (   0.00000,  -12.25911,   20.86043), 
 (   0.00000,   11.66443,   20.86043), 
 (   0.00000,  -12.25911,    2.57523), 
 (   0.00000,   11.66443,   20.86043), 
 (   0.00000,   11.66443,    2.57523)]

This will be a total of 8 triangles (and not the 4 that you would expect for two rectangular planes). So the rectangles essentially exist twice, in the same place. The result of that is severe z-fighting.

In https://gltf-viewer.donmccurdy.com/ , it looks like this:

Cesium Normal Flickering

and similarly in https://sandbox.babylonjs.com/

To fix this, you could modify the geometry of the model, to avoid the rectangles being duplicated, or simply make the material not double-sided, by removing the
"doubleSided": true,
part from the material definition.

It then looks like this:

Cesium Normal Flickering gone

The duplicated triangles might still cause other issues, but the appearance should then be fixed (I didn’t test it in CesiumJS yet, but assume that it will work there as well)


An aside: The model contains two accessors for texture coordinates, but they contain the same data. You could optimize this to use a single set of texture coordinates.

Thank you so much Marco! It’s rather obvious that it’s z-fighting now that you point it out. We had a condition forcing doubleSided if the texture is translucent, I just removed it now and it works fine. Our duplicated geometry is to make sure the lighting conditions are correct, to avoid dark backfaces.

I will look into the texture coordinate optimization as well, it’s solved in a more general way when converting from OpenFlight, but maybe we could check if they are identical and reuse them.

A short note regarding the optimization of deduplicating the texture coordinates: It depends on many factors for the specific use-case/application. But for many applications/libraries, one can make a strong case to not spend time for implementing something like that.

One should only try to re-invent the wheel when there is the chance of inventing a better wheel.

Specifically, when this is running in a node environment, then one should at least consider to simply plug in something like dedup | glTF Transform as a post-processing step for the (otherwise unoptimized) output. Re-implementing this from scratch will mean re-implementing bugs that have already been weeded out elsewhere. And the deduplication is only one optimization. Further optimizations (welding, flattening, Draco compression, …) can then be added a a single line of code, compared to … well, who would even try to implement a Draco encoder from scratch …?

(These are just thoughts, no (explicit) recommendation - these are engineering decisions that have to take the whole picture into account)

Great, thanks for the glTF-Transform suggestion, Marco. Sounds like a good solution.