Point sprite rendering issues with three.js

793 views Asked by At

I'm currently working an a project which will visualize data on browser by rendering excessive amounts of animated stroked circles. I started evaluating 3D libraries and ended up trying to create a proof of concept application with three.js. It is capable of animating and rendering up to 150 000 point sprites at 60 fps on my 1440p monitor. Everything looks great until you start looking at the details. It has two rendering issues:

  1. It creates strange horizontal lines even when you turn animation off
  2. When you turn the camera, transparent areas of overlapping point sprites will show the background instead of underlying point sprites

Here is the proof of concept application: https://jsfiddle.net/tcpvfbsd/1/

var renderer, scene, camera, controls;
var points;
var stats;
var controls;

var worldWidth = 200;
var worldRadius = worldWidth / 2;
var patchSize = 10;
var pointsAmount = 100000;

function init() {
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x1d252d);

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
  camera.position.set(0, worldWidth * 1.5, 0);

  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.minDistance = 100;
  controls.maxDistance = 1100;

  scene.add(new THREE.GridHelper(2 * worldRadius, 2 * worldWidth / patchSize, 0x444444, 0x444444));



  var geometry = new THREE.BufferGeometry();
  var positions = new Float32Array(pointsAmount * 3);
  var rotations = new Float32Array(pointsAmount * 1);

  for (var i = 0; i < pointsAmount; i++) {

    positions[i] = 0;
    positions[i + 1] = 0;
    positions[i + 2] = 0;
    rotations[i] = 2 * Math.PI * Math.random();

  }

  controls = new function() {
    this.speed = 10;
    this.amount = 10;
  };

  var gui = new dat.GUI();
  gui.add(controls, 'speed', 0, 100);
  //gui.add(controls, 'amount', 0, 10000).step(1);;

  geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
  geometry.addAttribute('rotation', new THREE.BufferAttribute(rotations, 1));

  var loader = new THREE.TextureLoader();
  loader.load('//i.imgur.com/AmQQnZc.png', function(texture) {
    var material = new THREE.PointsMaterial({
      size: 5,
      transparent: true,
      map: texture

    });

    points = new THREE.Points(geometry, material);
    scene.add(points);

    stats = new Stats();
    document.body.appendChild(stats.dom);
    animate();
  });

}

function animate() {

  requestAnimationFrame(animate);

  var position = points.geometry.attributes.position;
  var count = position.count;
  var rotation = points.geometry.attributes.rotation;
  var speed = patchSize * controls.speed / 100;
  if (speed > 0) {
    for (var i = 0; i < count; i++) {

      var wiggle = Math.random() > 0.9 ? THREE.Math.randFloat(-0.1, 0.1) : 0;
      var theta = rotation.getX(i) + wiggle;
      let dx = speed * Math.cos(theta);
      let dz = speed * Math.sin(theta);
      var x0 = position.getX(i);
      var z0 = position.getZ(i);
      var x = THREE.Math.clamp(x0 + dx, -worldRadius, worldRadius);
      var z = THREE.Math.clamp(z0 + dz, -worldRadius, worldRadius);
      if (Math.abs(x) === worldRadius) dx = -dx;
      if (Math.abs(z) === worldRadius) dz = -dz;
      position.setX(i, x);
      position.setZ(i, z);
      position.setY(i, 1);
      rotation.setX(i, Math.atan2(dz, dx));

    }
  }

  position.needsUpdate = true;

  stats.update();

  renderer.render(scene, camera);

}
init();

Best way to see the issues is to wait couple of seconds for the point sprites to spread across to area, use speed control on top right corner to pause animation and the use mouse's left button to turn and rotate the camera.

1

There are 1 answers

0
user1937459 On BEST ANSWER
  1. Using alphaTest with value 0.5 clipped the corners off the circles without affecting the rendering of other circles
  2. Setting transparent value to false removed the buggy fade effect which came after setting alphaTest to 0.5
  3. Adding fading to the texture itself made the circles' borders smooth even thought the transparent setting which caused the fade effect was disabled
  4. Randomizing the position on y axis by 0.01 units removed the strange horizontal lines