Three.js, custom shader and png texture with transparency

I have a very simple PNG texture: a gray circle with a transparent background.

PNG image with transparency

I use it as a single map for THREE.ShaderMaterial :

 var uniforms = THREE.UniformsUtils.merge( [basicShader.uniforms] ); uniforms['map'].value = THREE.ImageUtils.loadTexture( "img/particle.png" ); uniforms['size'].value = 100; uniforms['opacity'].value = 0.5; uniforms['psColor'].value = new THREE.Color( 0xffffff ); 

Here is my fragment shader (only part of it):

 gl_FragColor = vec4( psColor, vOpacity ); gl_FragColor = gl_FragColor * texture2D( map,vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) ); gl_FragColor = gl_FragColor * vec4( vColor, 1.0 ); 

I applied the material to some particles ( THREE.PointCloud mesh) and it works quite well:

Particles texture with transparency: OK!

But if I rotate the camera more than 180 degrees, I see this:

Particles texture without transparency

I understand that the fragment shader does not correctly take into account the alpha value of the PNG texture.

What is the best approach in this case to get the desired color and opacity (from user attributes) and still get alpha to the right of PNG?

And why does this work correctly on the one hand?

+5
source share
1 answer

Transparent objects should be displayed from beginning to end - from the farthest to the closest. This is because of the depth buffer.

But PointCloud particles are not sorted depending on the distance from the camera. That would be too inefficient. Particles are always displayed in the same order, regardless of the position of the camera.

You have several workarounds.

The first is to discard fragments for which alpha is low. You can use a template like this:

 if ( textureColor.a < 0.5 ) discard; 

Another option is to set material.depthTest = false or material.depthWrite = false. You may not like the side effects if you have other objects in the scene.

three.js r.71

+9
source

All Articles