Transparent textured face on transparent textured face rendering - three.js

Is there a way to correctly display more than one transparent texture in three.js? There are no problems if you try to render a transparent texture on a non-transparent textured plane below, but if you have more than a transparent plane, the nearest will "delete" the others below as you can see here:
On the left pic, there's what I would have (achieved adding depthWrite = false to every transparent material), on the right there's what I have, only setting transparent = true to materials with RGBA textures.
I already tried using alphaTest, but it isn't what I need, and depthWrite sometimes can't satisfy my needs (look at the green line bounding the path in the first screen, which hasn't been covered by the house shadow).

Related

Draw texture to FrameBufferObject using specific color

I have a texture and I want to draw it to a FrameBufferObject. The texture has transparent areas. I would like the following:
For all transparent pixels, let them be drawn transparent in the FrameBufferObject.
For all non-transparent pixels, let them be drawn using a color of my choosing, ie pure red (ignore their actual rgb value)
I've tried Batch.setColor(red) before drawing the texture, but that just tints it - I want all non-transparent pixels to be drawn pure red.
I am also trying to figure out how to achieve this in just opengl directly, looks like there may be a way to do this with blending, which can then be related back to gdx.
Thanks
You need to write a shader and the shader is the OpenGL program that renders the texture. So your shader would render transparency without change and all else would the color of your own choosing.
The following link has libgdx shaders for palette swapping i.e. direct reassignment of color at render, which you can easily adapt for single color and transparency.
https://www.javaer101.com/en/article/12241616.html

Shader with alpha masking other objects

I'm trying to make a very simple shadow shader which consists of a plane with a shader showing a radial gradient on colors and alpha.
Beneath this shadow lies another plane with the same kind of shader but linear.
And as a background of all this, a linear gradient from dark blue to light blue.
The problem is that when my camera approaches the ground, the plane of the shadow masks the floor.
Why does it happen and what can I do to prevent that?
https://codesandbox.io/s/epic-sun-po9j3
https://po9j3.csb.app/
You'd need to post code to check for sure but it likely happens because three.js sorts the order it draws things based on the center of the objects and their distance from the camera.
You can force a different order by setting Object3D.renderOrder
three.js also generally draws opaque things before transparent things so my guess is your ground plane and your shadow plane are both set to transparent: true but the ground can be set to transparent: false in which case it will be drawn first.
You might find this article useful. It shows a similar example.
As for why there is a hole it's because of the depth buffer. If something in front gets drawn first then the pixels behind are not drawn. So if the shadow happens to be drawn first it ends up looking like a hole because the pixels of plane behind it are not drawn.
See this

Black background for three.js sprites with depthTest true

I have been experimenting with converting the custom attribute BufferGeometry example (https://threejs.org/examples/webgl_buffergeometry_custom_attributes_particles.html) into a fly through animation and I find that the sprites have dark backgrounds (and those that I create myself as well) if depthTest is set to true. See the image.
The sprite in the custom attribute example has a transparent background but this appears to be ignored when it is rendered if depthTest is set to true.
I have tried numerous custom blending rules but cannot find a way to remove the background, only to reduce the effect a bit. The background disappears if depthTest is set to false.
Is this a known limitation? Is there a work around?
I am modifying this question to add clearer images with a different ball sprite (also with a transparent background). This image has depthTest set to true for the custom ShaderMaterial used in the https://threejs.org/examples/webgl_buffergeometry_custom_attributes_particles.html three.js example.
By comparison, this uses multiple PointsMaterials from a different three.js example (https://threejs.org/examples/webgl_points_sprites.html), also with depthTest set to true and using the PointsMaterial map parameter for the sprite.
As you can see, the second PointsMaterial example works as expected. Because PointsMaterial only accepts one fixed size and color, I need to create 36 different point geometries to render this image.
I would prefer to use the custom shader in the first example (which has custom size and color attributes and requires only one geometry). Is there a way to define a custom shader to support depthTest like the PointsMaterial does?
WebGL has a depth buffer that's used to find out which pixels are hiding behind other pixels. If a pixel is hiding behind another, it doesn't get rendered. Typically that's what you would want, why would you waste GPU time rendering pixels you're never going to see? Consider the example depthbuffer below, white squares are closer to the camera, while darker squares are further away:
If there was a square hiding behind another one, you wouldn't see it in the depthBuffer, you'd only see the closest one. The depthBuffer doesn't know that your squares have partial transparency and you want some parts to be see-through. This is an issue in other realtime engines too, this is an example from Unity:
The squares that are closer are blocking part of the squares that are further away in the depthBuffer, so the occluded pixels don't get rendered. That's why setting depthTest to false is useful. You're basically telling the renderer to stop testing which pixels are behind others, and just render all of them. Here it is again with depthTest = false:
If you must set depthTest on, (for instance, if you want the sprites to hide behind a solid wall) you could set depthWrite to false on the sprite material. It would still check which pixels are behind others, but the pixels from the sprites wouldn't get written to the depthBuffer, so no sprite could block another sprite.
depthTest: true; // Tests pixel depth
depthTest: false; // Does not test pixel depth
depthWrite: true; // Writes pixel depth to depthBuffer
depthWrite: false; // Does not write pixel depth to depthBuffer
As far as blending mode, I prefer THREE.AdditiveBlending because it gives the particles a nice glowing effect when they accumulate one on top of the other. But that's up to you.

Threejs transparent materials union blending

I have two different objects with the same transparent material in threejs, and I want to blend them in a "non-additive" way like in the following picture. There are three boxes: one blue in the background and two transparent yellow boxes in the foreground. The left image is how it currently is, and the right image is what I want. Is there a kind of material / possibly shader that can achieve this effect?

How can I have a png image with transparency, visible only from *front*?

I'm using a prefab for a box shape, which has a front and back plane.
My images are PNG and have transparent areas around the edge. I dragged the image onto my front plane, which now has a drop-down box for "Shader".
First I chose Shader: "Standard" but the transparent areas of my PNG image weren't transparent, so in order to fix that I changed it to "Sprites / Diffuse"... now the image looks fine (from the front).
However, when I rotate the shape, the image is also visible from the back. I want a way to not see the image / texture from the back.
How can I make the images only visible from the front side of a plane, whilst also preserving the transparency areas of the image / texture?
If you are using the standard built-in shader, you need to set the rendering mode to transparent in order for the texture's alpha channel to be transparent. The sprite shader, by default, forces the rendering of otherwise invisible back-faces, whereas the standard shader does not.

Resources