WebGL pointcloud / particles


I am trying to display a point cloud using WebGL.

Drawing a WebGL.entity per point is too slow, I have more than 300000 points.

So my idea was to create one mesh containing a fixed number of points (for example 307200) with colors and positions at 0 and the point index as attribute.
And then pass an array of positions and an array of colors as uniforms to update the points based on the index.

The problem is, in the current implementation of WebGL, it is not possible to pass arrays as uniforms or create floating point textures from arrays.
From what I understand this would require to modify the compiler. But I think it would be a really useful feature.

Do you have other ideas?

1 Like

Hi Jerome, if you need to animate every single point’s color individually every frame based on logic in Elm, then I don’t see an easy way to do it. You could create one large WebGL.points mesh with all 300000 points, and have position/index etc. as vertex attributes; is there perhaps some way to calculate each point’s color in the vertex shader based on the point’s index/position/other attributes plus some small (fixed) number of uniforms, instead of doing all that work on the CPU?

Could you create an example on Ellie showing what you’re trying to do? It may be that there is another solution…

Note: I don’t think passing an array uniform would work anyways, since it’s my understanding that array uniforms have to be a constant size (fixed at shader compile time). Generating a texture from an Elm array could indeed be a good solution, but would require some significant changes to Elm’s WebGL package.

Ian suggested to use a texture to pass array information to the shader and in fact you can generate a BMP image on the fly using https://package.elm-lang.org/packages/justgook/elm-image-encode/latest/

You can then load the texture as data-uri and access its content as sampler2D in the shader.

Of course if this array needs to change often it is not feasible since unfortunately it is quite inefficient—it’s a workaround, after all.

1 Like

Thank you for your replies, I will do some tests based on your suggestions.

Ideally I would need to update the position and color of every points at 30fps. Lower fps could be acceptable as long as the view stays responsive.

A fixed size array uniform is not really a problem, I can have dead/unused points in the mesh and in the array.

I also don’t think WebGL supports arrays of 300000 elements even if they are fixed size - the limit seems more like a couple hundred.

Thinking out loud, I wonder if you could have a dummy points mesh with (say) 64 points, each point just having an index attribute, then a vertex shader with 64 position and 64 color vec3s…then do something like some fancy bitwise operations in the shader to select the correct position and color uniform values based on the vertex index. This would at least let you draw in batches of 64 vertices at once, although I don’t know how efficient it would be to set a ton of uniforms.

This issue has been opened recently:

It mentions a workaround of having multiple uniforms and using the index attribute to choose which uniform to use. Doesn’t look nice in code, but may be worth trying.

Drawing by batches is a really good idea.

I started an Ellie:
I will complete it with the suggestions when I find the time.

I added drawing with batches of 32 points, it is already much better:

I guess some of the fps drop is also due to the multiple copies of my points as they are stored in the model.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.