Jump to content

Most performant way to render a point cloud


Recommended Posts

Hey y'all! New babylonjs dev here ?. I've been trying to render a huge point cloud, so far with 100k points (xyz), I tested these two methods:

  • Using a Solid Particle System (SPS): 13 FPS
  • Using a Sprite Manager: 28 FPS

I saw in the demos what legacy Particle Systems and GPU Particle Systems can do at solid 60 FPS, but I can't figure out a way to create particles individually and place them at certain positions (those provided by an array of positions).

What do you suggest?


Link to comment
Share on other sites

Thanks! ?

This is more or less the implementation I did for the SPS, I still get 13 FPS even in the Playground: https://www.babylonjs-playground.com/#WCDZS#85

As for the startPositionFunction in ParticleSystem, I'd need a way to create a fixed number of particles at once, since the emitters only allow for particle creation and destruction over time, although I might be mistaken ?

Link to comment
Share on other sites

Ok, I understand.

Whereas the sprite manager or the legacy particle system always render their elements (sprites or 2d particles) directly in the screen space in a certain manner, the SPS, even in billboard mode, still computes everything in the world space. So when using the billboard mode, the SPS needs to rotate each particle for you under the hood so they always face the camera ... and rotations are the heaviest computations in the process.

That's why I often recommend to use the legacy particle system or the sprite manager when people need the billboard mode for planar particles only because they are more powerful when dealing with huge number (> 10K) of particles.

That said, if you still want to use the SPS with billboard because of its extra features (per particle color, uvs, intersection, picking, particle depth sort for alpha blending, etc) and if you want to get higher performance, you could consider these leads, knowing that the heavy computation is done in setParticles() :

- don't call setParticles() at all if your camera doesn't need to rotate (but only to zoom in/out, so no need for billboard there) and keep the planar particles : https://www.babylonjs-playground.com/#WCDZS#86

- if the camera needs to rotate, call setParticles() only on demand : https://www.babylonjs-playground.com/#WCDZS#87

- don't call setParticles() at all, don't use the billboard mode, and replace the planar particles by real 3D particles visible from everywhere (tetrahedrons or tiny low poly spheres)

tetras : https://www.babylonjs-playground.com/#WCDZS#88

icospheres : https://www.babylonjs-playground.com/#WCDZS#89

boxes : https://www.babylonjs-playground.com/#WCDZS#90


300K fixed boxes : https://www.babylonjs-playground.com/#WCDZS#91


BTW, I'm currently working on my poor free time on a wasm test about the SPS computation process to check if this could be really improved with wasm. This is really painful because WASM doesn't provide any math function like sine, cosine that are massively used in the rotation computations. So I have first to reimplement some sine and cosine before making the SPS test.

Link to comment
Share on other sites

Thanks for the answer @jerome!

Just for context, I'm trying to achieve similar performance to this point cloud renderer: Potree. It seems to use billboard with even more than 3 million planes with next to no performance issues, although it could be using some optimizations when zooming out rendering less planes, I'm not sure.

I've tested the legacy particle system with 100k points too, and I seem to be getting around 35 FPS, not a huge increase.

The performance without billboard in SPS is stellar, and it'd be neat to have access to all those per-particle functions, although the scene seems to take very long to load if using 3D particles. Is there some way to optimize this?

Link to comment
Share on other sites

Have been having a play around to see if I could get anything with faster fps. First try is to build a mesh just from the points data and use pointsCloud on the material. No indices, no normals so no light just black points https://www.babylonjs-playground.com/#WZNWVG

The only way I could think of to add color was to form small triangles around each point and then I realised that if I did that and put the mesh into billboardMode the points cloud would already exist https://www.babylonjs-playground.com/#WZNWVG#1

3 million points (that's 9 million vertices) is possible but not at 60fps, I was getting 25fps on my laptop https://www.babylonjs-playground.com/#WZNWVG#2

Since normals will always be (0, 0, -1) because of the way the facets are constructed they can be added at construction rather than calculated later (only 300 000 points this time so waiting not too long) https://www.babylonjs-playground.com/#WZNWVG#3

For info offset determines the size of each of the triangles.

Have fun


Link to comment
Share on other sites

@jerome makes sense ?

@JohnK I didn't think about building a mesh from scratch! This seems to be what I was looking for, hopefully, as it doesn't somehow perform expensive billboard computations (I don't quite understand how it's done). Though it doesn't seem to work in the stable release, only in the beta.

Regarding the color, I've found that you can set the color per vertex, so no need to form triangles without that precious billboard effect: https://www.babylonjs-playground.com/#WZNWVG#5

Although the performance is a bit worse  than with your implementation at 3 million points, but I guess I can live with that: https://www.babylonjs-playground.com/#WZNWVG#6

Link to comment
Share on other sites

Found some raw data here added some commas and turned into an array and could not save the array in the PG as got `too long` message so had to add as external file to get


Give it a moment or two to load up. If it says 'positions not defined` click the RUN button.

Link to comment
Share on other sites

@JohnK That's cool! Although when you have huge xyz files, you'll probably want to use some kind of data stream in order to not run out of memory.

The problem I have now is that I lost some SPS functionality, including the very important ability to pick the points individually. I was wondering if there's a way to do this in BJS without tackling with WebGL directly. I've been scouting through the forum and the documentation, but couldn't find much ?

Link to comment
Share on other sites

To better illustrate what I meant: https://www.babylonjs-playground.com/#WZNWVG#11 (console logs whether it's picked or not)

The goal is to be able to tell the position of the vertices you click or hover with the cursor, this way it could be possible to measure distances or angles between different points.

Thanks for the help!

Edit: Should I make this a separate question? I posted it here just because it was related.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...