leaflet.glmarkers

GL markers with custom shaders for your LeafletJS maps

Usage no npm install needed!

<script type="module">
  import leafletGlmarkers from 'https://cdn.skypack.dev/leaflet.glmarkers';
</script>

README

Leaflet.GLMarkers

A LeafletJS plugin to create markers with WebGL shaders.

Demo

There is an interactive demo! That demo uses some predefined data and one predefined texture, and lets you play with the shaders.

Compatibility

Leaflet 1.0.3 (or newer), and a web browser that supports both WebGL and ES6 Promises. You can also use a Promise polyfill for IE11.

Usage

Include Leaflet and Leaflet.GLMarkers in your HTML:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css"
  integrity="sha512-07I2e+7D8p6he1SIM+1twR5TIrhUQn9+I6yjqD53JQjFiMf8EtC93ty0/5vJTZGF8aAocvHYNEDJajGdNx1IsQ=="
  crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet-src.js"
  integrity="sha512-WXoSHqw/t26DszhdMhOXOkI7qCiv5QWXhH9R7CgvgZMHz1ImlkVQ3uNsiQKu5wwbbxtPzFXd1hK4tzno2VqhpA=="
  crossorigin=""></script>
  
<script src='https://unpkg.com/leaflet.glmarkers@latest/dist/Leaflet.GLMarkers.js'></script>

(Alternatively, fetch a local copy of Leaflet and Leaflet.GLMarkers with npm install --save leaflet; npm install --save leaflet.glmarkers or yarn add leaflet; yarn add leaflet.glmarkers)

Then, write some GLSL shader code, and have it as a Javascript string. See the interactive demo for some code patterns you can copy-paste.

Initialize a L.GLMarkerGroup like so:

    var glMarkers = new L.GLMarkerGroup({
        // The "attributes" option lets you write "attribute float megacity",
        // "attribute float rank_min", etc in your vertex shader.
        // These attributes will be populated with the values in each GLMarker.
        attributes: ['megacity', 'rank_min', 'rank_max', 'labelrank', 'adm0cap'],
        
        // The "texture" option lets you use up to 8 images as textures.
        // In this example, we'll have an image of a kitten in the first 
        // texture, which has to be referred to as "uniform Sampler2D uTexture0"
        // in the fragment shader.
        textures: ['http://placekitten.com/g/128/128'],
        
        // And the GLMarkerGroup needs the vertex and fragment shaders
        // code as strigns.
        vertexShader: vertexCode,
        fragmentShader: fragCode
    }).addTo(map);

And lastly, add some L.GLMarkers to your .GLMarkerGroup:

    glMarkers.addMarker( new L.GLMarker(
        [latitude, longitude],
        { megacity: 0, labelrank: 5, adm0cap: 1 }
    ) );

It's recommended that you read some "vanilla" WebGL tutorials and resources, such as https://webglfundamentals.org/ and http://thebookofshaders.com/ . Those will explain basic WebGL concepts such as attributes, varyings and uniforms.

A L.GLMarkerGroup will create four vertices per L.GLMarker (in two triangles). Each vertex for a GLMarker will have the same attributes aCRSCoords and aLatLngCoords, plus an attribute called aExtrudeCoords which is different for each of the four vertices (with respective values of [-1, -1], [-1, +1], [+1, -1], and [+1, +1].

Besides those attributes, you can specify custom attributes during the instantiation of your GLMarkerGroup, as seen above.

The following uniforms are defined:

  • uTransformMatrix (to convert the aCRSCoords into clipspace coordinates)
  • uPixelSize (to convert pixels into clipspace coordinate deltas)
  • uNow (time in milliseconds elapsed since the webpage was loaded)
  • uTexture0 through uTexture7 (up to 8 textures, as per the textures option when the GLMarkerGroup was instantiated)

It's the responsability of your vertex shader to put those attributes and uniforms to good use. See some common patterns in the interactive demo. The file demo/deml.html shows a minimal Leaflet map and GLMarkerGroup.

Motivation

This is @xavijam's fault, because he launched a coding challenge and I thought it would be a nice pasttime.

This also follows the work done in Leaflet.TileLayer.GL: do the heavy lifting of initializing WebGL and creating triangles with the proper CRS coordinates, while letting the user add points and style the shaders. This should let more people use WebGL to do cartographic stuff, without having to rely on more complex frameworks.

Legalese


"THE BEER-WARE LICENSE": ivan@sanchezortega.es wrote this file. As long as you retain this notice you can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return.