Intro:
I need insights on how to achieve what is described below. I’ve tried many things but have found no perfect solution yet. I am not sure if I am struggling due to lack of knowledge about THREEJS, or some limitation, or some design decision of the framework, or a bug, or what not. Any help is appreciated.
Goal:
To be able to display (in the XY plane) a stack of plane meshes (not the same Z value), each containing a semi-transparent gray-scale texture map and a background color for tinting, such that viewing the entire stack of planes gives the impression that they form a single and more complex image.
Issue:
When viewing 2 partially overlapping plane meshes of the same background color and both having partially transparent PNG texture maps, the edges of the texture (where transparency transitions from opaque to fully transparent) produce a subtle yet awful looking seam between the two meshes.
Expected behavior:
Continuing from the description above. Since the material of the 2 planes will look like a partially transparent image of the same color, it is expected that there would be no seam when they overlap, as if the 2 planes were a single and bigger texture of a single color.
Example:
2 plane meshes with same background color (0xF1BDAE) and same semi-transparent gray-scale texture (from SymbolArtEditorOnline/241.png at 421a0379abb9916a20c4e0700b054c1fda2ba440 · malulleybovo/SymbolArtEditorOnline · GitHub). In it, the is a subtle seam on the right edge of the left disk. Since the texture is completely white + alpha, the plane should be entirely one color + alpha. On the edge of the texture, it should take up the color value of what is beneath (which is the exact same color. But it doesn’t do so and results in a seam.
This seam gets worse when zooming out as well.
This is the code for the mesh and the material. I tried using multiple types of custom blending, all of which just made it worse. The “best” result so far was this code, but this result is still unacceptable for the project it will go on since it is a premise that there will never be seams.
// mesh for each of the disks in the image.
new THREE.Mesh(/* geometry below */, /* material below */);
new THREE.ShapeGeometry(new THREE.Shape([
new THREE.Vector2(-1, 1),
new THREE.Vector2(1, 1),
new THREE.Vector2(1, -1),
new THREE.Vector2(-1, -1)
]))
new THREE.MeshBasicMaterial({
color: color.value,
transparent: true,
side: THREE.DoubleSide,
opacity: opacity.value
})
Another example of the seams below, this time in a more complex image of an arm pointing to the side made of multiple meshes. Note that the skin color got really ugly due to the multiple seams that were never supposed to be there,
Details of the scenario of usage:
- Uses new THREE.WebGLRenderer({ powerPreference: ‘high-performance’, antialias: true })
- Uses new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 1) for viewing (camera direction -Z)
- Stacks meshes in the 3D scene with enough delta-Z to avoid aliasing and are displayed in the XY-plane at some Z.
- meshes use the same code shared above for the mesh, geometry, and material. The geometry may be changed to stretch any corner of any mesh.
Conclusing:
The project is currently unreleased work, but will be open-source in the near future. It is highly desirable that this gets fixed before release, but I am running out of thoughts on how to address this.
- I’ve spent a good amount of time trying to use THREE.CustomBlending options to no avail.
- I’ve doubted it was the texture image at fault, but it wasn’t (I have another project using it with PixiJS and pixi does a wonderful job in this regard, though it is only 2D; plus the image is fully white and transparent so it cannot display more that one RGB color when tinting).
- I’ve thought about changing the material to a THREE.ShaderMaterial and doing everything my way, but that’s the extreme end of solutions to me, which is why I am posting this question. I have not tried this yet and want to avoid it if at all possible.
Are there any leads on how to remove these seams from transparent textures?