Add a new WebGLPointsLayer type using the shader builder utilities
This required adding a `a_index` attribute in the points layer renderer to be able to make the precomputed shaders to work.
This commit is contained in:
@@ -240,3 +240,7 @@ Support for the `OES_element_index_uint` WebGL extension is mandatory for WebGL
|
|||||||
### 64
|
### 64
|
||||||
|
|
||||||
Layer opacity must be a number.
|
Layer opacity must be a number.
|
||||||
|
|
||||||
|
### 65
|
||||||
|
|
||||||
|
A symbol literal representation must be defined on the style supplied to a `WebGLPointsLayer` instance.
|
||||||
|
|||||||
69
src/ol/layer/WebGLPoints.js
Normal file
69
src/ol/layer/WebGLPoints.js
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* @module ol/layer/WebGLPoints
|
||||||
|
*/
|
||||||
|
import VectorLayer from './Vector.js';
|
||||||
|
import {assign} from '../obj.js';
|
||||||
|
import WebGLPointsLayerRenderer from '../renderer/webgl/PointsLayer.js';
|
||||||
|
import {getSymbolFragmentShader, getSymbolVertexShader} from '../webgl/ShaderBuilder.js';
|
||||||
|
import {assert} from '../asserts.js';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Options
|
||||||
|
* @property {import('../style/LiteralStyle.js').LiteralStyle} literalStyle Literal style to apply to the layer features.
|
||||||
|
* @property {string} [className='ol-layer'] A CSS class name to set to the layer element.
|
||||||
|
* @property {number} [opacity=1] Opacity (0, 1).
|
||||||
|
* @property {boolean} [visible=true] Visibility.
|
||||||
|
* @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be
|
||||||
|
* rendered outside of this extent.
|
||||||
|
* @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers
|
||||||
|
* will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed
|
||||||
|
* for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()`
|
||||||
|
* method was used.
|
||||||
|
* @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be
|
||||||
|
* visible.
|
||||||
|
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
||||||
|
* be visible.
|
||||||
|
* @property {import("../source/Vector.js").default} [source] Source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc
|
||||||
|
* Layer optimized for rendering large point datasets.
|
||||||
|
* Note that any property set in the options is set as a {@link module:ol/Object~BaseObject}
|
||||||
|
* property on the layer object; for example, setting `title: 'My Title'` in the
|
||||||
|
* options means that `title` is observable, and has get/set accessors.
|
||||||
|
*
|
||||||
|
* @fires import("../render/Event.js").RenderEvent
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
class WebGLPointsLayer extends VectorLayer {
|
||||||
|
/**
|
||||||
|
* @param {Options} options Options.
|
||||||
|
*/
|
||||||
|
constructor(options) {
|
||||||
|
const baseOptions = assign({}, options);
|
||||||
|
|
||||||
|
super(baseOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import('../style/LiteralStyle.js').LiteralStyle}
|
||||||
|
*/
|
||||||
|
this.literalStyle = options.literalStyle;
|
||||||
|
|
||||||
|
assert(this.literalStyle.symbol !== undefined, 65);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
createRenderer() {
|
||||||
|
return new WebGLPointsLayerRenderer(this, {
|
||||||
|
vertexShader: getSymbolVertexShader(this.literalStyle.symbol),
|
||||||
|
fragmentShader: getSymbolFragmentShader()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WebGLPointsLayer;
|
||||||
@@ -123,9 +123,9 @@ const tmpArray_ = [];
|
|||||||
const bufferPositions_ = {vertexPosition: 0, indexPosition: 0};
|
const bufferPositions_ = {vertexPosition: 0, indexPosition: 0};
|
||||||
|
|
||||||
export const POINT_INSTRUCTIONS_COUNT = 13;
|
export const POINT_INSTRUCTIONS_COUNT = 13;
|
||||||
export const POINT_VERTEX_STRIDE = 12;
|
export const POINT_VERTEX_STRIDE = 13;
|
||||||
|
|
||||||
function writePointVertex(buffer, pos, x, y, offsetX, offsetY, u, v, opacity, rotateWithView, red, green, blue, alpha) {
|
function writePointVertex(buffer, pos, x, y, offsetX, offsetY, u, v, opacity, rotateWithView, red, green, blue, alpha, index) {
|
||||||
buffer[pos + 0] = x;
|
buffer[pos + 0] = x;
|
||||||
buffer[pos + 1] = y;
|
buffer[pos + 1] = y;
|
||||||
buffer[pos + 2] = offsetX;
|
buffer[pos + 2] = offsetX;
|
||||||
@@ -138,6 +138,7 @@ function writePointVertex(buffer, pos, x, y, offsetX, offsetY, u, v, opacity, ro
|
|||||||
buffer[pos + 9] = green;
|
buffer[pos + 9] = green;
|
||||||
buffer[pos + 10] = blue;
|
buffer[pos + 10] = blue;
|
||||||
buffer[pos + 11] = alpha;
|
buffer[pos + 11] = alpha;
|
||||||
|
buffer[pos + 12] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeCustomAttrs(buffer, pos, customAttrs) {
|
function writeCustomAttrs(buffer, pos, customAttrs) {
|
||||||
@@ -202,19 +203,19 @@ export function writePointFeatureToBuffers(instructions, elementIndex, vertexBuf
|
|||||||
const baseIndex = vPos / stride;
|
const baseIndex = vPos / stride;
|
||||||
|
|
||||||
// push vertices for each of the four quad corners (first standard then custom attributes)
|
// push vertices for each of the four quad corners (first standard then custom attributes)
|
||||||
writePointVertex(vertexBuffer, vPos, x, y, -size / 2, -size / 2, u0, v0, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, -size / 2, -size / 2, u0, v0, opacity, rotateWithView, red, green, blue, alpha, 0);
|
||||||
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
vPos += stride;
|
vPos += stride;
|
||||||
|
|
||||||
writePointVertex(vertexBuffer, vPos, x, y, +size / 2, -size / 2, u1, v0, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, +size / 2, -size / 2, u1, v0, opacity, rotateWithView, red, green, blue, alpha, 1);
|
||||||
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
vPos += stride;
|
vPos += stride;
|
||||||
|
|
||||||
writePointVertex(vertexBuffer, vPos, x, y, +size / 2, +size / 2, u1, v1, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, +size / 2, +size / 2, u1, v1, opacity, rotateWithView, red, green, blue, alpha, 2);
|
||||||
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
vPos += stride;
|
vPos += stride;
|
||||||
|
|
||||||
writePointVertex(vertexBuffer, vPos, x, y, -size / 2, +size / 2, u0, v1, opacity, rotateWithView, red, green, blue, alpha);
|
writePointVertex(vertexBuffer, vPos, x, y, -size / 2, +size / 2, u0, v1, opacity, rotateWithView, red, green, blue, alpha, 3);
|
||||||
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
writeCustomAttrs(vertexBuffer, vPos + baseStride, customAttrs);
|
||||||
vPos += stride;
|
vPos += stride;
|
||||||
|
|
||||||
|
|||||||
@@ -408,6 +408,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
this.helper.enableAttributeArray(DefaultAttrib.OPACITY, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 6);
|
this.helper.enableAttributeArray(DefaultAttrib.OPACITY, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 6);
|
||||||
this.helper.enableAttributeArray(DefaultAttrib.ROTATE_WITH_VIEW, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 7);
|
this.helper.enableAttributeArray(DefaultAttrib.ROTATE_WITH_VIEW, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 7);
|
||||||
this.helper.enableAttributeArray(DefaultAttrib.COLOR, 4, FLOAT, bytesPerFloat * stride, bytesPerFloat * 8);
|
this.helper.enableAttributeArray(DefaultAttrib.COLOR, 4, FLOAT, bytesPerFloat * stride, bytesPerFloat * 8);
|
||||||
|
this.helper.enableAttributeArray('a_index', 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 12);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -568,6 +569,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
|
|||||||
this.helper.enableAttributeArray(DefaultAttrib.OPACITY, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 6);
|
this.helper.enableAttributeArray(DefaultAttrib.OPACITY, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 6);
|
||||||
this.helper.enableAttributeArray(DefaultAttrib.ROTATE_WITH_VIEW, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 7);
|
this.helper.enableAttributeArray(DefaultAttrib.ROTATE_WITH_VIEW, 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 7);
|
||||||
this.helper.enableAttributeArray(DefaultAttrib.COLOR, 4, FLOAT, bytesPerFloat * stride, bytesPerFloat * 8);
|
this.helper.enableAttributeArray(DefaultAttrib.COLOR, 4, FLOAT, bytesPerFloat * stride, bytesPerFloat * 8);
|
||||||
|
this.helper.enableAttributeArray('a_index', 1, FLOAT, bytesPerFloat * stride, bytesPerFloat * 12);
|
||||||
|
|
||||||
const renderCount = this.indicesBuffer_.getSize();
|
const renderCount = this.indicesBuffer_.getSize();
|
||||||
this.helper.drawElements(0, renderCount);
|
this.helper.drawElements(0, renderCount);
|
||||||
|
|||||||
56
src/ol/style/LiteralStyle.js
Normal file
56
src/ol/style/LiteralStyle.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* Literal Style objects differ from standard styles in that they cannot
|
||||||
|
* be functions and are made up of simple objects instead of classes.
|
||||||
|
* @module ol/style/LiteralStyle
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Here are a few samples of literal style objects:
|
||||||
|
* ```js
|
||||||
|
* const style = {
|
||||||
|
* symbol: {
|
||||||
|
* symbolType: 'circle',
|
||||||
|
* size: 8,
|
||||||
|
* color: '#33AAFF',
|
||||||
|
* opacity: 0.9
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const style = {
|
||||||
|
* symbol: {
|
||||||
|
* symbolType: 'image',
|
||||||
|
* offset: [0, 12],
|
||||||
|
* size: [4, 8],
|
||||||
|
* src: '../static/exclamation-mark.png'
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @typedef {Object} LiteralStyle
|
||||||
|
* @property {LiteralSymbolStyle} [symbol] Symbol representation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @enum {string}
|
||||||
|
*/
|
||||||
|
export const SymbolType = {
|
||||||
|
CIRCLE: 'circle',
|
||||||
|
SQUARE: 'square',
|
||||||
|
TRIANGLE: 'triangle',
|
||||||
|
IMAGE: 'image'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} LiteralSymbolStyle
|
||||||
|
* @property {number|Array.<number, number>} size Size, mandatory.
|
||||||
|
* @property {SymbolType} symbolType Symbol type to use, either a regular shape or an image.
|
||||||
|
* @property {string} [src] Path to the image to be used for the symbol. Only required with `symbolType: 'image'`.
|
||||||
|
* @property {import("../color.js").Color|string} [color='#FFFFFF'] Color used for the representation (either fill, line or symbol).
|
||||||
|
* @property {number} [opacity=0] Opacity.
|
||||||
|
* @property {Array.<number, number>} [offset] Offset on X and Y axis for symbols. If not specified, the symbol will be centered.
|
||||||
|
* @property {Array.<number, number, number, number>} [textureCoord] Texture coordinates. If not specified, the whole texture will be used (range for 0 to 1 on both axes).
|
||||||
|
* @property {boolean} [rotateWithView=false] Specify whether the symbol must rotate with the view or stay upwards.
|
||||||
|
*/
|
||||||
@@ -16,17 +16,8 @@ export function formatNumber(v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} SymbolShaderParameters
|
* Generates a symbol vertex shader from a literal style,
|
||||||
* @property {number|Array.<number, number>} size Size.
|
* intended to be used on point geometries.
|
||||||
* @property {boolean} [rotateWithView] Rotate with view.
|
|
||||||
* @property {Array.<number, number>} [offset] Offset.
|
|
||||||
* @property {Array.<number, number, number, number>} [textureCoord] Texture coordinates: u0, v0, u1, v1.
|
|
||||||
* @property {number} [opacity] Opacity.
|
|
||||||
* @property {import("../color.js").Color|string} [color] Color.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a symbol vertex shader, i.e. a shader intended to be used on point geometries.
|
|
||||||
*
|
*
|
||||||
* Expected the following attributes to be present in the attribute array:
|
* Expected the following attributes to be present in the attribute array:
|
||||||
* `vec2 a_position`, `float a_index` (being the index of the vertex in the quad, 0 to 3).
|
* `vec2 a_position`, `float a_index` (being the index of the vertex in the quad, 0 to 3).
|
||||||
@@ -34,7 +25,7 @@ export function formatNumber(v) {
|
|||||||
* Transmits the following varyings to the fragment shader:
|
* Transmits the following varyings to the fragment shader:
|
||||||
* `vec2 v_texCoord`, `float v_opacity`, `vec4 v_color`
|
* `vec2 v_texCoord`, `float v_opacity`, `vec4 v_color`
|
||||||
*
|
*
|
||||||
* @param {SymbolShaderParameters} parameters Parameters for the shader.
|
* @param {import('../style/LiteralStyle.js').LiteralSymbolStyle} parameters Parameters for the shader.
|
||||||
* @returns {string} The full shader as a string.
|
* @returns {string} The full shader as a string.
|
||||||
*/
|
*/
|
||||||
export function getSymbolVertexShader(parameters) {
|
export function getSymbolVertexShader(parameters) {
|
||||||
@@ -82,7 +73,7 @@ void main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a symbol fragment shader, i.e. a shader intended to be used on point geometries.
|
* Generates a symbol fragment shader intended to be used on point geometries.
|
||||||
*
|
*
|
||||||
* Expected the following varyings to be transmitted by the vertex shader:
|
* Expected the following varyings to be transmitted by the vertex shader:
|
||||||
* `vec2 v_texCoord`, `float v_opacity`, `vec4 v_color`
|
* `vec2 v_texCoord`, `float v_opacity`, `vec4 v_color`
|
||||||
|
|||||||
Reference in New Issue
Block a user