Issue with OIT feature

When I enable OIT through scene.useOrderIndependentTransparency = true;, the edges of translucent triangles are visible.
They are not visible if OIT is disabled.
Any idea?

PG here (sorry, the file is ~100MB, so it takes a few seconds to load):

w000t never seen this before and I have even no idea how it is possible, let me add @CraigFeldspar to the thread

hello @Michael
Looked at your PG, and found that you have lots of opaque and alpha meshes in your model.

Can you check that you don’t have 2 meshes layered on top of each other that share the exact same depth ? This usually doesn’t play well with OIT

Let me know

1 Like

Hi, thanks for the answer and sorry for the delay. Indeed, at the exact location of the edges bug, there are two meshes at the exact same depth.

But in the playground and in my Babylon.js v5.0.0 locally, I do not reproduce the issue (even without moving the meshes to have different depth…) So I don’t really know what happened here.

However, I found what it looks like a bug when using OIT : in my code I :

  • Activate OIT
  • append a glTF file as a file containing semi-transparent textures
  • Clear the mesh using mesh.dispose()
  • Add another mesh using Append

Then, if OIT is activated, all the textures that are semi-transparent are not cleared and remains in the scene. Even if I clear all the scene by iterating over scene.meshes, the semi-transparent textures are not cleared. This issue is not here if I disable OIT. Do you have any ideas ?

I am trying to reproduce the issue in the playground

@CraigFeldspar will fix it in no time with a playground sounds like a dispose issue :slight_smile:

Here is the playground

Sorry for ugly code, but the issue is here. If you disable oit it works, but if you enable it, you notice that the transparent textures stay at the same location on the screen. It looks like we are not flushing the dual-depth peeling framebuffers or something like that !

Thanks, @CraigFeldspar for your feedback.
My previous PG is not working anymore, please try this new one:

I managed to run Spectorjs on this one, showing that even the first draw call is showing these black edge artifacts, so I don’t think it’s related to two meshes at the same location:

@CraigFeldspar My guess on the issue: my glTF doesn’t have tangents attribute, so the TBN matrix is computed using dFdx and dFdy. However, the derivatives must be called unconditionally, and it seems that the shader can return before cotangent_frame which uses the derivatives.

That s a pretty good catch, @CraigFeldspar should be able to look into it soon :slight_smile:

@sebavan @CraigFeldspar any update?
I was able to confirm that the bug isn’t visible when my glTF file includes tangents, so it’s definitely related to cotangent_frame being called after the potential return resulting in undefined derivatives.

1 Like

Hi Michael,

Sorry I’m really swamp these days, I may be able to look into it over the weekend.
I’ll keep you posted

1 Like

So it all boils down to this line in bumpFragmentMainFunctions.fx, l44 :

float invmax = inversesqrt(max(dot(tangent, tangent), dot(bitangent, bitangent)));

The expression inside the inverse square root can be sometimes 0, so the inverse op breaks the shading of the pixel.

I was able to have a correct shading by safeguarding the value :
float invmax = inversesqrt(max(0.00001, max(dot(tangent, tangent), dot(bitangent, bitangent))));

I really don’t like this solution though.

@sebavan @Evgeni_Popov would you happen to know in what case dFdx(p) would return 0 ? This op is related to the neighbouring fragments, so something may happen there.

Btw I tried to move the OIT part that was returning before the use of derivatives, as @Michael suggested, and it has no effect :confused: Maybe we need to find a way to avoid this branching at all ?


Are you sure it is dFdx(p) which returns 0 and not dFdx(uv) / dFdy(uv)? We already had a problem with dFdx(uv) / dFdy(uv), see Anisotropy Issues - Worse on Mac OS - #9 by Evgeni_Popov.

The fix would be to explicitely provide tangents instead of trying to compute them with the cotangent frame.

However, your fix may well be ok, to avoid crashing the shader.

1 Like

I am fine with safe guarding @CraigFeldspar could you create a PR ???

Safeguarding derivates in bump shader by CraigFeldspar · Pull Request #12242 · BabylonJS/Babylon.js · GitHub Here you go :slight_smile: