Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alpha in Fragment Shader gl_FragColor not working

Tags:

three.js

glsl

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: 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:false

depthTest true: depthTest:true

like image 490
Jonathan Plackett Avatar asked Oct 18 '25 16:10

Jonathan Plackett


1 Answers

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.

like image 98
Marquizzo Avatar answered Oct 20 '25 15:10

Marquizzo