Cesium is designed to take advantage of GPU hardware. In most cases this means using WebGL to render 3D objects onto the screen. While WebGL is primarily a graphics library, it can be utilized to do more general computing tasks.
This concept is called GPGPU, or General-Purpose computing on Graphics Processing Units. GPGPU is also known as GPU computing. The GPU is a massively parallel machine. While its first use was to speed up rasterization for 3D rendering, researchers soon discovered that they could use it to solve other highly parallelizable tasks. Initially the only way to harness the GPU was through graphics APIs such as OpenGL, but now we have compute-dedicated APIs such as CUDA, OpenCL, and compute shaders.
Under the hood in the Cesium renderer we have built a compute pass on top of WebGL. The technique is pretty standard:
- Create a framebuffer. We will render to a texture instead of directly to the screen.
- Set the texture size and viewport size to match the size of the compute task.
- Render a full-screen quad to generate the correct number of fragments. The vertex shader is often minimal.
- The fragment shader does the actual compute work. Each fragment is one parallel process of the compute task. After performing any necessary calculations, the fragment writes its result to a texture.
There are a couple of places in Cesium that use this pipeline. For example, we generate the sun texture on the fly based on screen size and glow factors. Also, we reproject globe imagery from Web Mercator to geographic coordinates (see Slides 39-43 in Rendering the Whole Wide World on the World Wide Web). In both cases, Cesium uses WebGL to perform a compute task that renders to a texture.
We streamlined this process by introducing compute commands, which exist alongside draw and clear commands (for more on commands, see the Renderer Architecture). Now primitives can issue compute commands instead of performing these steps themselves. The scene collects any compute commands and executes them before rendering the scene. So, for example, a texture written by a compute command can be used by a draw command later that frame.
The compute pass, which executes compute commands, is general enough to handle a wide variety of tasks. We expect to add additional features that take advantage of this new stage, including a post-processing framework and particle system.