Plugin for massive markers rendering & animation - cesium-gpu-points-layer

Hello, forum!

TLDR: cesium-gpu-points-layer allows you to render massive amounts of dynamic markers billboard-style or parallel to the globe surface. Over a million simultaneous icons around the globe is possible at low graphics settings. It provides a considerable performance improvement over CPU-hungry Billboards. How much depends on the client machine’s CPU vs GPU productivity.

How does it work?

GpuPointLayer receives a marker URL with other configuration options and provides a custom primitive that can be added to the scene. The marker is rasterised into a virtual canvas and converted into a texture for shader uniforms. Points describing markers’ locations, rotations, and movements can be passed via a method or in the layer constructor. This data is converted into a texture (or two textures if we need animation) and passed to shaders as uniforms as well.
The core of the library is the DrawCommand based on PrimitiveType.POINTS and shaders built by the lib. The command is pushed to frameState.commandList by our primitive in its update method.
Exact positions and other marker properties are derived from textures in code running on the GPU. I think this is the main reason it can offer performance improvements. In the vertex shader, locations are converted from Cartographic to Cartesian coordinates, then to world and eye coordinates, and finally multiplied by czm_projection, yielding our point’s gl_Position. gl_PointSize is defined by cameraDistance and the marker layer configuration. When alignWithGround is enabled, the vertex shader computes v_groundAlignment: how compressed the marker should be (e.g. near globe edge) and v_flattenAxisScreen: compression axis angle in screen space.
Fragment shader samples pixels from our texture and applies rotation and “flattening” logic, if needed.

Why was it made?

I was making a pet project whilst learning NestJS and something involving “high load”. I settled on querying public APIs and collecting aircraft movement data, earthquakes, weather data, ships, etc. But I also wanted a nice frontend showing all that geospatial data. CesiumJS was the best tool for the job. While playing around with massive amounts of markers, I noticed that performance-wise, it was not great. Thinking about possible solutions to this problem, I imagined a transparent sphere enclosing the globe and a custom shader that renders millions of small markers around the globe this way. I got carried away from my initial NestJS business and focused on this interesting problem. Eventually, after brainstorming ideas with ChatGPT and Codex, GL_POINTS-based solution looked most promising. I was genuinely surprised that it not only worked more or less as I imagined, but was indeed noticeably more performant. So it could be useful to other people! After a few weeks and some polishing, I think it’s ready for potential public scrutiny and potential real users.
I hope some people will find it useful, or even review the code/report problems/suggest improvements/contribute/etc.

Refs

This is the library’s source code GitHub - vadimrostok/cesium-gpu-points-layer · GitHub
This is live demo Cesium GPU Point Layer Demo GitHub page, and this is the demo repository showcasing lib’s usage GitHub - vadimrostok/cesium-gpu-points-layer-demo · GitHub
Small screen recording demo: https://youtu.be/EdOW_UQYjG0?si=1TRe7o6f1PGtU96M

5 Likes

I wasn’t able to find a way to add showcase tag. Maybe because I’m a new user. Otherwise, I’d appreciate if someone’d let me know how to do that…
Another screenshot:

1 Like

well done. great!

1 Like