2
votes

WHAT I'M DOING

I'm rendering circular points with varying vertex colors using a fragment shader. I in essence want the points to act as more performant spheres that are antialiased when zoomed all the way in.

PROBLEM

It works in one direction (see left photo), but the other direction has white corners (see right photo). How do I get rid of the white corners?

Direction I want it to look like What I don't want

WHAT I TRIED

  • If the points were all the same color, I could turn off depthTest and it would just work. However, the points must be varying colors. Turning off the depthTest with varying colors makes it look like a wormhole.
  • I tried alphaTest to no avail. I did get alphaTest to work with textures instead of a custom fragment shader (png of a circle on transparent background), but it looked blurry when zoomed in sufficiently.
  • I did notice that the colors of the corners was equivalent to whatever I passed into renderer.setClearColor.
  • I've played around with blending options, but I'm not familiar enough with blending yet to understand what I'm doing.

CODE

const geometry = new THREE.BufferGeometry();
geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
const material = new THREE.ShaderMaterial({
  transparent: true,
  vertexColors: THREE.VertexColors,
  uniforms: {
      size: {value: 20},
      scale: {value: 10},
  },
  defines: {
    USE_MAP: "",
    USE_SIZEATTENUATION: ""
  },
  vertexShader: THREE.ShaderLib.points.vertexShader,
  fragmentShader: `
  in vec3 vColor;
  void main() {
      vec2 xy = gl_PointCoord.xy - vec2(0.5);
      float ll = length(xy);
      gl_FragColor = vec4(vColor, step(ll, 0.5));
  }
  `
});
const points = new THREE.Points( geometry, material );
scene.add( points );

Thanks for the help!

1
Try to put if (ll > 0.5) discard; after float ll = length(xy);, and remove transparent: true.prisoner849

1 Answers

2
votes

To remove those corners, you can discard the pixels, whose length of UV position is greater than 0.5:

  in vec3 vColor;
  void main() {
      vec2 xy = gl_PointCoord.xy - vec2(0.5);
      float ll = length(xy);
      if (ll > 0.5) discard; // this line does the trick
      gl_FragColor = vec4(vColor, step(ll, 0.5));
  }