Update the icon-sprite-webgl example to use a WebGLPoints layer
This commit is contained in:
@@ -3,13 +3,13 @@ layout: example.html
|
|||||||
title: Icon Sprites with WebGL
|
title: Icon Sprites with WebGL
|
||||||
shortdesc: Rendering many icons with WebGL
|
shortdesc: Rendering many icons with WebGL
|
||||||
docs: >
|
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
|
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
|
icon marks a UFO sighting according to its reported shape (disk, light, fireball...). The older the sighting, the redder
|
||||||
the icon.
|
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`
|
A very simple sprite atlas is used in the form of a PNG file containing all icons on a grid. Then, the `style` object
|
||||||
option of the `ol/renderer/webgl/PointsLayer` constructor is used to specify which sprite to use according to the sighting shape.
|
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
|
The dataset contains around 80k points and can be found here: https://www.kaggle.com/NUFORC/ufo-sightings
|
||||||
tags: "webgl, icon, sprite, point, ufo"
|
tags: "webgl, icon, sprite, point, ufo"
|
||||||
|
|||||||
+33
-159
@@ -4,11 +4,9 @@ import TileLayer from '../src/ol/layer/Tile.js';
|
|||||||
import TileJSON from '../src/ol/source/TileJSON.js';
|
import TileJSON from '../src/ol/source/TileJSON.js';
|
||||||
import Feature from '../src/ol/Feature.js';
|
import Feature from '../src/ol/Feature.js';
|
||||||
import Point from '../src/ol/geom/Point.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 {Vector} from '../src/ol/source.js';
|
||||||
import {fromLonLat} from '../src/ol/proj.js';
|
import {fromLonLat} from '../src/ol/proj.js';
|
||||||
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer.js';
|
import WebGLPointsLayer from '../src/ol/layer/WebGLPoints.js';
|
||||||
import {colorToGlsl, numberToGlsl} from '../src/ol/style/expressions.js';
|
|
||||||
|
|
||||||
const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg';
|
const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg';
|
||||||
|
|
||||||
@@ -17,161 +15,40 @@ const vectorSource = new Vector({
|
|||||||
attributions: 'National UFO Reporting Center'
|
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 oldColor = [255, 160, 110];
|
||||||
const newColor = [180, 255, 200];
|
const newColor = [180, 255, 200];
|
||||||
const size = 16;
|
const size = 16;
|
||||||
|
|
||||||
class WebglPointsLayer extends VectorLayer {
|
const style = {
|
||||||
createRenderer() {
|
symbol: {
|
||||||
return new WebGLPointsLayerRenderer(this, {
|
symbolType: 'image',
|
||||||
attributes: [
|
src: 'data/ufo_shapes.png',
|
||||||
{
|
size: size,
|
||||||
name: 'year',
|
color: [
|
||||||
callback: function(feature) {
|
'interpolate',
|
||||||
return feature.get('year');
|
['stretch', ['get', 'year'], 1950, 2013, 0, 1],
|
||||||
}
|
oldColor,
|
||||||
},
|
newColor
|
||||||
{
|
],
|
||||||
name: 'texCoordU',
|
rotateWithView: false,
|
||||||
callback: function(feature) {
|
offset: [
|
||||||
let coords = shapeTextureCoords[feature.get('shape')];
|
0,
|
||||||
if (!coords) {
|
9
|
||||||
coords = shapeTextureCoords['default'];
|
],
|
||||||
}
|
textureCoord: [
|
||||||
return coords[0];
|
'match',
|
||||||
}
|
['get', 'shape'],
|
||||||
},
|
'light', [0, 0, 0.25, 0.5],
|
||||||
{
|
'sphere', [0.25, 0, 0.5, 0.5],
|
||||||
name: 'texCoordV',
|
'circle', [0.25, 0, 0.5, 0.5],
|
||||||
callback: function(feature) {
|
'disc', [0.5, 0, 0.75, 0.5],
|
||||||
let coords = shapeTextureCoords[feature.get('shape')];
|
'oval', [0.5, 0, 0.75, 0.5],
|
||||||
if (!coords) {
|
'triangle', [0.75, 0, 1, 0.5],
|
||||||
coords = shapeTextureCoords['default'];
|
'fireball', [0, 0.5, 0.25, 1],
|
||||||
}
|
[0.75, 0.5, 1, 1]
|
||||||
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(' ')
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
function loadData() {
|
function loadData() {
|
||||||
const client = new XMLHttpRequest();
|
const client = new XMLHttpRequest();
|
||||||
@@ -217,8 +94,9 @@ const map = new Map({
|
|||||||
crossOrigin: 'anonymous'
|
crossOrigin: 'anonymous'
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
new WebglPointsLayer({
|
new WebGLPointsLayer({
|
||||||
source: vectorSource
|
source: vectorSource,
|
||||||
|
style: style
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
target: document.getElementById('map'),
|
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.';
|
info.innerText = 'On ' + datetime + ', lasted ' + duration + ' seconds and had a "' + shape + '" shape.';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
texture.addEventListener('load', function() {
|
|
||||||
map.render();
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user