I'm using Three.js and a ShaderMaterial to draw Points Geometry with a Fragment Shader.
I want each point to have a blurred edge, but I can't get the alpha to work, it just turns white.
I can discard pixels when they're completely transparent to make a circle, but the blur fades to white and is then abruptly cut off.
Here's what I see on screen:
Three.JS code
var shaderMaterial = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexshader' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
blending: THREE.NormalBlending,
depthTest: true,
transparent: true,
clipping: true
});
var points = new THREE.Points(geometry, shaderMaterial);
Fragment Shader:
//translate gl_PointCoord to be centered at 0,0
vec2 cxy = 2.0 * gl_PointCoord - 1.0;
//calculate alpha based on distance from centre
//(I'm doubling it to get a less gradual fade)
float newAlpha = (1.0-distance(cxy, vec2(0.0,0.0))) * 2.0;
if (newAlpha < 0.01)
{
//discard pixels that have ~0 alpha
discard;
}
gl_FragColor = vec4( newR, newG, newB, newAlpha);
Thanks in advance for any help :) This has been puzzling me for AGES.
Edit: Images of depthTest on and off. It looks to me like depth test does put them in the right order?
depthTest false:
depthTest true:
Your JSFiddle example has several instances where it fights with itself. You're trying to set the material blending mode in Three.js, but then you override that with:
var gl = renderer.context;
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
You're requesting an animationFrame
, but then do a setTimeout inside of that, removing all benefits of using animationFrame
.
I was able to get something slightly improved with
blending: THREE.NormalBlending,
transparent: true,
depthWrite: false,
depthTest: true
You can see the fixes live here: https://jsfiddle.net/yxj8zvmp/
... although there are too many attributes and uniforms being passed to your geometry to really get to the bottom of why the depth isn't working as expected. Why are you passing u_camera
, when you already have cameraPosition, and your position
attribute is of length 1
? It feels like a blend of raw WebGL fighting with Three.js.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With