Rendering Artificats on Safari iOS 14: PBRMaterial + Depth Prepass + IBL

Hello everyone,

first of all we would like to thank you for the quick babylonjs support we are getting, it’s really amazing! Also, congratulations on the 4.2 release :partying_face:

In our current project we are using transparent materials a lot and babylonjs does a really great job at rendering them with the depth prepass option. It works quite well on WebGL 2.0. On WebGL 1.0 iOS 14 however, rendering artifacts which look at lot like Z-Fighting appear when used in combination with a PBRMaterial and IBL. This is not specifically a WebGL 1.0 issue because by forcing WebGL 1.0 we are not able to reproduce this issue on other devices. These rendering artifacts do not appear with a StandardMaterial or without IBL. Enabling WebGL 2.0 Preview on iOS 14.0.1 also fixes the issue however this is not an option for production.

Test device with the issue: iPad Gen 7 iOS 14.0.1
Other WebGL 1.0 devices without the issue: iPad Air 2 iOS 13.3, iPad Pro Gen 3 iOS 13.3.1

Sandbox to reproduce the problem:

Edit: iOS 14.2 has also the issue.

Pinging @Cedric and @sebavan (please just be patient as the team is resting a bit after the release )

It unfortunately looks like a bug on their webgl 1 implementation :frowning: I am trying to see if there are any workarounds.

basically their less or equal on depth seems to fail and not find values equal on the same exact inputs :frowning:

Could you create a bug on their side ?

Their switch to angle will definitely address this but in the mean time you can not really use the pre pass … or would need to hack some scale down version of the mesh for it…

As a weird side not it looks like it only happens with texturelod use

Ok scratch all I said before :slight_smile: this is a workaround :

    mat.forceIrradianceInFragment = true;

This makes totally no sense so I am trying to dig further in :slight_smile:

1 Like

Thanks sebavan! This workaround fixes the issue :slight_smile:

Even though it’s a workaround I will mark your answer as a solution for now.

After some more digging, it would seem the problem could come from the fact that the precision used in the vertex shader is automatically lowered when some threshold is reached, like the number of instructions or uniforms used.

When rendering the mesh in the second phase (regular rendering), the threshold is reached so the precision is lowered, whereas in the first phase (depth pre-pass) the threshold is not reached and the mesh is rendered with full precision. That means the z-depth values don’t match anymore between the first and second phases, leading to z-fighting.

Unfortunately we can’t do much on our side, this behaviour is hard-coded in the OS/drivers (IF it is the right explanation).