Transparent png rendering weird when overlaping two PlaneGeometry

Hi, this is what I want to achieve in Three.js

This is my texture:
image

And when I merge two PlaneGeometry with that texture in transparent: true
This happen:
image

My code:

const geometry = new THREE.PlaneGeometry(1, 1)
const textureLoaded = new THREE.TextureLoader().load(url)
const material = new THREE.MeshBasicMaterial({
    // color: 0xffffff,
    map: textureLoaded,
    transparent: true

})
const mesh = new THREE.Mesh(geometry, material)
//...

What you see there is z-fighting, so what you’re trying can be better archived by keeping those grassy details inside your tile - but making it seamless to the neighbour tiles which is perfectly possible for your pattern. You can set alphaTest: 0.5 in your material to reduce the black border, but it won’t help with z-fighting which will be only a little less visible as the colors are similar.

To get overlapping on the edges/cliffs like in your first picture you can use a set of 4 tiles wich have only 1 side with the grass overlapping each.

Another approach is using decals, for decals there are a couple methods, but archiving transparent ones which aren’t projected on a geometry is harder as you’re again have to avoid z-fighting. One thing in this regard helping is using a logarithmic depth buffer and a minimal offset increasing by distance - but remember enabling logarithmicDepthBuffer for the renderer will also come with a cost and rather pays off when your scene renders large distances and therefore requires it.

Little addition: It seems to me that you don’t have to set transparent to true for your use case.

Not sure if I understand this. You mean like making perfect squares and adding those details like a texture pattern?

alphaTest: 0.5 Is helping but as you said they are still z-fighting when are very different colors.

To get overlapping on the edges/cliffs like in your first picture you can use a set of 4 tiles wich have only 1 side with the grass overlapping each.

Could you clarify this?

I was thinking of removing the outside details into a new texture and put it on top.

You are right does not affect.

Exactly, when you add them seamless the result will look the same.

Basically you have a tile for each of 4 sides so you only add a tile hanging over the edge. This is a quite common technique for 2D as well as 3D games. Ideally you would make the plane only the width of the overhang but for simplicity it’s enough.

I can’t do this because I’m gonna have like 6-8 different types of tiles and cant make a pattern for all the variants.

I see, for now I’m just focusing on the grass. But good to know for the future. Thank you :slight_smile:

Another thing you could consider is using texture splatting for your grass (transparent layers on top of your tiles), which basically is the most simple kind of decal, you might take a look at this pen. I see what you mean with different terrain types and the overlapping grass, you basically have your ground texture and use 1-4 transparent tiles on top depending on the neighbour tile, it is a bit more complicated but possible and gives the desired result. Anyway good luck :cat:

2 Likes

I just got the effect I wanted. But I’m facing an impact on performance. Because my scene has like 50x50 tiles. And I’m creating a PlaneGeometry for each tile. So in my computer is ok, but I’d like this to work on mobiles too. The problem is that tiles will have different decoration sprites. And not sure what technique to use to create an 50x50 terrain that looks like this:
image

I see that you are using fragments in your example to overlay multiple textures, but for me fragments are like Chinese.

You can use THREE.InstancedMesh in case you want every tile to be a plane, this will significantly improve the performance, but here you need to move your tile information about which edge cases it has into an extra THREE.InstancedBufferAttribute, depending on how you solved it now (decal or overlay).

There are 2 ways you can deal with different textures then, either you use a InstancedMesh for every kind of texture such as grass and dirt, or you use just one and put your textures into an atlas, this is a bit more complex though and introduces problems you need to avoid if you can’t use WebGL2 (bleeding etc).

1 Like