From a64f2eb7207aa9adc9263801ff5946ab5fcb5425 Mon Sep 17 00:00:00 2001 From: Olivier Guyot Date: Fri, 25 Oct 2019 10:24:51 +0200 Subject: [PATCH] Update the icon-sprite-webgl example to use a WebGLPoints layer --- examples/icon-sprite-webgl.html | 6 +- examples/icon-sprite-webgl.js | 192 ++++++-------------------------- 2 files changed, 36 insertions(+), 162 deletions(-) diff --git a/examples/icon-sprite-webgl.html b/examples/icon-sprite-webgl.html index 92dd5cfdf9..2af2b66f59 100644 --- a/examples/icon-sprite-webgl.html +++ b/examples/icon-sprite-webgl.html @@ -3,13 +3,13 @@ layout: example.html title: Icon Sprites with WebGL shortdesc: Rendering many icons with WebGL docs: > - This example shows how to use `ol/renderer/webgl/PointsLayer` to render + This example shows how to use `ol/layer/WebGLPoints` to render a very large amount of sprites. The above map is based on a dataset from the National UFO Reporting Center: each icon marks a UFO sighting according to its reported shape (disk, light, fireball...). The older the sighting, the redder the icon. - A very simple sprite atlas is used in the form of a PNG file containing all icons on a grid. Then, the `texCoordCallback` - option of the `ol/renderer/webgl/PointsLayer` constructor is used to specify which sprite to use according to the sighting shape. + A very simple sprite atlas is used in the form of a PNG file containing all icons on a grid. Then, the `style` object + given to the `ol/layer/WebGLPoints` constructor is used to specify which sprite to use according to the sighting shape. The dataset contains around 80k points and can be found here: https://www.kaggle.com/NUFORC/ufo-sightings tags: "webgl, icon, sprite, point, ufo" diff --git a/examples/icon-sprite-webgl.js b/examples/icon-sprite-webgl.js index 6f21136610..dff30fdd36 100644 --- a/examples/icon-sprite-webgl.js +++ b/examples/icon-sprite-webgl.js @@ -4,11 +4,9 @@ import TileLayer from '../src/ol/layer/Tile.js'; import TileJSON from '../src/ol/source/TileJSON.js'; import Feature from '../src/ol/Feature.js'; import Point from '../src/ol/geom/Point.js'; -import VectorLayer from '../src/ol/layer/Vector.js'; import {Vector} from '../src/ol/source.js'; import {fromLonLat} from '../src/ol/proj.js'; -import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer.js'; -import {colorToGlsl, numberToGlsl} from '../src/ol/style/expressions.js'; +import WebGLPointsLayer from '../src/ol/layer/WebGLPoints.js'; const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg'; @@ -17,161 +15,40 @@ const vectorSource = new Vector({ attributions: 'National UFO Reporting Center' }); -const texture = new Image(); -texture.src = 'data/ufo_shapes.png'; - -// This describes the content of the associated sprite sheet -// coords are u0, v0 for a given shape (all icons have a size of 0.25 x 0.5) -const shapeTextureCoords = { - 'light': [0, 0], - 'sphere': [0.25, 0], - 'circle': [0.25, 0], - 'disc': [0.5, 0], - 'oval': [0.5, 0], - 'triangle': [0.75, 0], - 'fireball': [0, 0.5], - 'default': [0.75, 0.5] -}; - const oldColor = [255, 160, 110]; const newColor = [180, 255, 200]; const size = 16; -class WebglPointsLayer extends VectorLayer { - createRenderer() { - return new WebGLPointsLayerRenderer(this, { - attributes: [ - { - name: 'year', - callback: function(feature) { - return feature.get('year'); - } - }, - { - name: 'texCoordU', - callback: function(feature) { - let coords = shapeTextureCoords[feature.get('shape')]; - if (!coords) { - coords = shapeTextureCoords['default']; - } - return coords[0]; - } - }, - { - name: 'texCoordV', - callback: function(feature) { - let coords = shapeTextureCoords[feature.get('shape')]; - if (!coords) { - coords = shapeTextureCoords['default']; - } - return coords[1]; - } - } - ], - uniforms: { - u_texture: texture - }, - vertexShader: [ - 'precision mediump float;', - - 'uniform mat4 u_projectionMatrix;', - 'uniform mat4 u_offsetScaleMatrix;', - 'uniform mat4 u_offsetRotateMatrix;', - 'attribute vec2 a_position;', - 'attribute float a_index;', - 'attribute float a_year;', - 'attribute float a_texCoordU;', - 'attribute float a_texCoordV;', - 'varying vec2 v_texCoord;', - 'varying float v_year;', - - 'void main(void) {', - ' mat4 offsetMatrix = u_offsetScaleMatrix;', - ' float offsetX = a_index == 0.0 || a_index == 3.0 ? ', - ' ' + numberToGlsl(-size / 2) + ' : ' + numberToGlsl(size / 2) + ';', - ' float offsetY = a_index == 0.0 || a_index == 1.0 ? ', - ' ' + numberToGlsl(-size / 2) + ' : ' + numberToGlsl(size / 2) + ';', - ' vec4 offsets = offsetMatrix * vec4(offsetX, offsetY, 0.0, 0.0);', - ' gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;', - ' float u = a_index == 0.0 || a_index == 3.0 ? a_texCoordU : a_texCoordU + 0.25;', - ' float v = a_index == 2.0 || a_index == 3.0 ? a_texCoordV : a_texCoordV + 0.5;', - ' v_texCoord = vec2(u, v);', - ' v_year = a_year;', - '}' - ].join(' '), - fragmentShader: [ - 'precision mediump float;', - - 'uniform float u_time;', - 'uniform float u_minYear;', - 'uniform float u_maxYear;', - 'uniform sampler2D u_texture;', - 'varying vec2 v_texCoord;', - 'varying float v_year;', - - 'void main(void) {', - ' vec4 textureColor = texture2D(u_texture, v_texCoord);', - ' if (textureColor.a < 0.1) {', - ' discard;', - ' }', - - // color is interpolated based on year - ' float ratio = clamp((v_year - 1950.0) / (2013.0 - 1950.0), 0.0, 1.1);', - ' vec3 color = mix(vec3(' + colorToGlsl(oldColor) + '),', - ' vec3(' + colorToGlsl(newColor) + '), ratio);', - - ' gl_FragColor = vec4(color, 1.0) * textureColor;', - ' gl_FragColor.rgb *= gl_FragColor.a;', - '}' - ].join(' '), - hitVertexShader: [ - 'precision mediump float;', - - 'uniform mat4 u_projectionMatrix;', - 'uniform mat4 u_offsetScaleMatrix;', - 'uniform mat4 u_offsetRotateMatrix;', - 'attribute vec2 a_position;', - 'attribute float a_index;', - 'attribute vec4 a_hitColor;', - 'attribute float a_texCoordU;', - 'attribute float a_texCoordV;', - 'varying vec2 v_texCoord;', - 'varying vec4 v_hitColor;', - - 'void main(void) {', - ' mat4 offsetMatrix = u_offsetScaleMatrix;', - ' float offsetX = a_index == 0.0 || a_index == 3.0 ? ', - ' ' + numberToGlsl(-size / 2) + ' : ' + numberToGlsl(size / 2) + ';', - ' float offsetY = a_index == 0.0 || a_index == 1.0 ? ', - ' ' + numberToGlsl(-size / 2) + ' : ' + numberToGlsl(size / 2) + ';', - ' vec4 offsets = offsetMatrix * vec4(offsetX, offsetY, 0.0, 0.0);', - ' gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0) + offsets;', - ' float u = a_index == 0.0 || a_index == 3.0 ? a_texCoordU : a_texCoordU + 0.25;', - ' float v = a_index == 2.0 || a_index == 3.0 ? a_texCoordV : a_texCoordV + 0.5;', - ' v_texCoord = vec2(u, v);', - ' v_hitColor = a_hitColor;', - '}' - ].join(' '), - hitFragmentShader: [ - 'precision mediump float;', - - 'uniform sampler2D u_texture;', - 'varying vec2 v_texCoord;', - 'varying vec4 v_hitColor;', - - 'void main(void) {', - ' vec4 textureColor = texture2D(u_texture, v_texCoord);', - ' if (textureColor.a < 0.1) {', - ' discard;', - ' }', - - ' gl_FragColor = v_hitColor;', - '}' - ].join(' ') - }); +const style = { + symbol: { + symbolType: 'image', + src: 'data/ufo_shapes.png', + size: size, + color: [ + 'interpolate', + ['stretch', ['get', 'year'], 1950, 2013, 0, 1], + oldColor, + newColor + ], + rotateWithView: false, + offset: [ + 0, + 9 + ], + textureCoord: [ + 'match', + ['get', 'shape'], + 'light', [0, 0, 0.25, 0.5], + 'sphere', [0.25, 0, 0.5, 0.5], + 'circle', [0.25, 0, 0.5, 0.5], + 'disc', [0.5, 0, 0.75, 0.5], + 'oval', [0.5, 0, 0.75, 0.5], + 'triangle', [0.75, 0, 1, 0.5], + 'fireball', [0, 0.5, 0.25, 1], + [0.75, 0.5, 1, 1] + ] } -} - +}; function loadData() { const client = new XMLHttpRequest(); @@ -217,8 +94,9 @@ const map = new Map({ crossOrigin: 'anonymous' }) }), - new WebglPointsLayer({ - source: vectorSource + new WebGLPointsLayer({ + source: vectorSource, + style: style }) ], target: document.getElementById('map'), @@ -242,7 +120,3 @@ map.on('pointermove', function(evt) { info.innerText = 'On ' + datetime + ', lasted ' + duration + ' seconds and had a "' + shape + '" shape.'; }); }); - -texture.addEventListener('load', function() { - map.render(); -});