10
votes

I am trying to use the Three.js library to display a large number of colored points on the screen (about half a million to million for example). I am trying to use the Canvas renderer rather than the WebGL renderer if possible (The web pages would also be displayed in the Google Earth Client bubbles, which seems to work with Canvas renderer but not the WebGL renderer.)

While I have the problem solved for a small number of points (tens of thousands) by modifying the code from here, I am having trouble scaling it beyond that.

But in the the following code using WebGL and the Particle System I can render half a million random points, but without colors.

  ...
var particles = new THREE.Geometry();
var pMaterial = new THREE.ParticleBasicMaterial({
                    color: 0xFFFFFF,
                    size: 1,
                    sizeAttenuation : false
                    });

// now create the individual particles
for (var p = 0; p < particleCount; p++) {
     // create a particle with randon position values,
     // -250 -> 250
     var pX = Math.random() * POSITION_RANGE - (POSITION_RANGE / 2),
     pY = Math.random() * POSITION_RANGE - (POSITION_RANGE / 2),
     pZ = Math.random() * POSITION_RANGE - (POSITION_RANGE / 2),
     particle = new THREE.Vertex(
                        new THREE.Vector3(pX, pY, pZ)
                        );

     // add it to the geometry
     particles.vertices.push(particle);
    }

    var particleSystem = new THREE.ParticleSystem(
                            particles, pMaterial);
    scene.add(particleSystem);
  ...

Is the reason for the better performance of the above code due to the Particle System? From what I have read in the documentation it seems the Particle System can only be used by the WebGL renderer.

So my question(s) are

a) Can I render such large number of particles using the Canvas renderer or is it always going to be slower than the WebGL/ParticleSystem version? If so, how do I go about doing that? What objects and or tricks do I use to improve performance?

b) Is there a compromise I can reach if I give up some features? In other words, can I still use the Canvas renderer for the large dataset if I give up the need to color the individual points?

c) If I have to give up the Canvas and use the WebGL version, is it possible to change the colors of the individual points? It seems the color is set by the material passed to the ParticleSystem and that sets the color for all the points.

1
You can use context2d drawImage() method to render your webGL canvas onto a 2d one.Kaiido

1 Answers

20
votes

EDIT: ParticleSystem and PointCloud has been renamed to Points. In addition, ParticleBasicMaterial and PointCloudMaterial has been renamed to PointsMaterial.

To have a different color for each particle, you need to have a color array as a property of the geometry, and then set vertexColors to THREE.VertexColors in the material, like so:

// vertex colors
var colors = [];
for( var i = 0; i < geometry.vertices.length; i++ ) {

    // random color
    colors[i] = new THREE.Color();
    colors[i].setHSL( Math.random(), 1.0, 0.5 );

}
geometry.colors = colors;

// material
material = new THREE.PointsMaterial( {
    size: 10,
    transparent: true,
    opacity: 0.7,
    vertexColors: THREE.VertexColors
} );

// point cloud
pointCloud = new THREE.Points( geometry, material );

Here is an updated Fiddle: http://jsfiddle.net/J7zp4/200/

Your other questions are a little too general for me to answer, and besides, it depends on exactly what you are trying to do and what your requirements are. Yes, you can expect Canvas to be slower.

EDIT: Updated for three.js r.73