Node Material - Z Offset / Fighting

Hi,

BabylonJS has some nice material properties for z-fighing - namely z offset.
But this time, I have one mesh and one material and the mesh is overlapping with itself. This normally causes z-fighting.

(A use case could be web map vector tiles. They contain vertex data that could be merged to one big mesh with only one material. But since the mesh contains overlapping elements, such as a pond within a park, it would lead to z-fighting.)

Now I have experimented with the Node Material Editor in the linked playground.
It takes uv coordinates of a merged mesh (0.6 for first ground mesh and 0.2 second) and adds their value to the the w value of the vertex position. It is a minimal increase, but seems to get the job done to avoid z-fighting. However, the w value seems to scale the model if increased to much. So I am not sure, if there will be side effects.

Is there a better way to have z-offset within node shader depending on a mesh property?

https://playground.babylonjs.com/#CPGQ4C

Kind regards!

Adding @PatrickRyan ?

Looking into this one to see if I can come up with a solution.

1 Like

@dennemark, unfortunately I was unable to find a better solution than what you are already doing since we can’t do multiple passes and we aren’t able to modify the depth slope of the triangles in node material. The only suggestion I have for you would be to scale the float that you are multiplying your UVs with based on the scale you are passing to the mesh. This would eliminate the problem with minimal management in your code.

Obviously, if you were to split the meshes this could handled by the zOffset in the node material. And in your example of a pond in the middle of a ground plane, I would want a separate shader on the water anyway. Even for a stylized effect that has no vertex displacement, I would want some sort of motion in a pattern in the base color to imply water. For the ground, you would want a different/simpler shader but if both were using the same shader, you would be paying for the heavier water shader for every pixel of ground that bypasses that technique in the shader. You increase your cost with an additional material and mesh, but you save on per-pixel operations, so you may end up ahead in that sense.

And if you are going with a simple representation of water and ground through single colors, you could still do that all in one shader on one mesh with no coplanar faces by allowing the shader to create the color breaks for you. You also have the added benefit of more resolution in the texture that you likely would in mesh. This technique would need to use math to create your color breaks and not textures as you would be limited by texel density if using textures. However, you should be able to create pond-like shapes and position them within your ground plane programmatically if you like.

All of these directions rely heavily in your camera placement, scene complexity, how you want the user to interact, etc. so there is no silver bullet here. I wish I could have given you a better answer, but there are a lot of trade-offs here.

2 Likes

@PatrickRyan thanks a lot for the thorough investigation!
Concerning the water I totally agree. I guess it wasn’t the best example. At the end I am using a seperate shader for water.

I guess my approach with adding small values to the w-value should serve as a work around atm. I have an atlas texture and can use the v-value of uv to define the zOffset.

Concerning the color-breaks approach, do I understand it right, that I would not use a polygon-like shape for the pond, but an algorithmically generated one?

@dennemark, yes, if you were to use a color-break approach, you would only need one mesh for the ground, and then you would locate your pond through UV space with an algorithmically-generated shape.

A very simple approach might look something like this:

which is generated from:

This way the shape would be independent of texture resolution. You would need to add more to the shader to be able to position and scale the pond, but this gives you an idea of what I was talking about.
Babylon.js Node Material Editor (babylonjs.com)

1 Like

@PatrickRyan thanks for your effort. Its a nice approach. Currently i need to work with geometries though.

I used a seperate shader for water now, as u stated. The remaining part works out except for some issues (left circle). But that is acceptable :slight_smile:

1 Like