Rendering points with WebGL

In the previous step, we rendered point features with the normal vector layer. This layer uses the 2D canvas context for rendering. With this layer, you can render tens of thousands of points – as long as you are careful about writing efficient styling code. For rendering larger numbers of points, or to do more efficient dynamic styling, WebGL is a good solution. OpenLayers has a growing set of utilities for rendering with WebGL. WebGL rendering is currently limited to points, and that is what we'll do in this exercise.

First, we'll import the constructor for the WebGL point renderer and a math utility function:

import Renderer from 'ol/renderer/webgl/PointsLayer';
import {clamp} from 'ol/math';

Next, we'll create a custom layer using the WebGL PointsLayer renderer. To create a custom layer, we need to override the createRenderer function returning our renderer instance. We construct this renderer with colorCallback and sizeCallback functions to determine the color and size of rendererd points.

const color = [1, 0, 0, 0.5];

class CustomLayer extends VectorLayer {
  createRenderer() {
    return new Renderer(this, {
      colorCallback: function(feature, vertex, component) {
        return color[component];
      sizeCallback: function(feature) {
        return 18 * clamp(feature.get('mass') / 200000, 0, 1) + 8;

In the layers array for your map, replace the VectorLayer with an instance of your CustomLayer using the same vector source as before.

new CustomLayer({
  source: source

Tada! Meteorite impact locations rendered with WebGL.

Square craters
Square craters

Unfortunately, we'd rather see these as circles instead of squares, so we'll need to do some work (this may change before the final 6.0 release).

To get our points rendered as circles, we need to create a custom fragment shader. We'll pass the shader to the WebGL points layer renderer as a string fragmentShader property of the second argument to the renderer constructor. The fragment shader is written in OpenGL Shading Language (GLSL). If you're interested in learning more about shaders and WebGL, take a look at The Book of Shaders.

Add the fragmentShader below to the options passed to the point renderer (along with colorCallback and sizeCallback).

fragmentShader: `
  precision mediump float;

  varying vec2 v_texCoord;
  varying vec4 v_color;

  void main(void) {
    vec2 texCoord = v_texCoord * 2.0 - vec2(1.0, 1.0);
    float sqRadius = texCoord.x * texCoord.x + texCoord.y * texCoord.y;
    float value = 2.0 * (1.0 - sqRadius);
    float alpha = smoothstep(0.0, 1.0, value);

    gl_FragColor = v_color;
    gl_FragColor.a *= alpha;

Looking better! The shader above uses the smoothstep function to turn what was a square into a circle. Fiddle with the values passed to smoothstep to see if you can get a feel for how it works.

Circular craters
Circular craters

results matching ""

    No results matching ""